/*
 * Wonders form JS Library 
 * Copyright (c) 2003-2007 Wonders Information Co.,Ltd. All Rights Reserved.
 * Ext 2.0 including override method
 */

Ext.ns('Ext.ux.form');

/*******************************************************************************
 * 表单控件扩展
 ******************************************************************************/
Wonders.form.HtmlForm = Ext.extend(Ext.form.FormPanel, {
	// \u7528\u4e8e\u5904\u7406\u5185\u7f6e\u7684grid\uff0c\u8c22\u56fd\u94a7
	gridArray : [],

	errorStyle : 'firstalert',

	doLayout : function(shallow) {

	},

	// private
	initComponent : function() {
		this.form = this.createForm();

		this.bodyCfg = {
			tag : 'form',
			action : this.url || '',
			// cls: this.baseCls + '-body',
			method : this.method || 'POST',
			id : this.id || Ext.id()
		};
		if (this.fileUpload) {
			this.bodyCfg.enctype = 'multipart/form-data';
		}
		if (this.items.length == 0) {
			this.items = new Ext.util.MixedCollection();
		}
		Ext.form.FormPanel.superclass.initComponent.call(this);

		this.addEvents(
		/**
		 * event clientvalidation If the monitorValid config option is true,
		 * this event fires repetitively to notify of valid state param
		 * {Ext.ux.HtmlForm} this param {Boolean} valid true if the form has
		 * passed client-side validation
		 */
		'clientvalidation');

		this.relayEvents(this.form, [ 'beforeaction', 'actionfailed',
				'actioncomplete' ]);
	},

	// private
	onRender : function(ct, position) {
		this.initFields();

		// Ext.ux.HtmlForm.superclass.onRender.call(this, ct, position);
		Ext.Panel.superclass.onRender.call(this, ct, position);
		var children = Ext.DomQuery.select("*", Ext.fly(ct).dom);
		this.el = Ext.fly(ct).createChild(this.bodyCfg);
		if (children) {
			for (var i = 0; i < children.length; i++) {
				if (children[i].parentNode == Ext.fly(ct).dom) {
					this.el.appendChild(children[i]);
				}
			}
		}

		var el = this.el, d = el.dom;
		this.body = this.el;
		if (this.cls) {
			this.el.addClass(this.cls);
		}

		this.form.initEl(this.body);
	},

	getErrorStyle : function() {
		return this.errorStyle;
	},
	/**
	 * *
	 * \u589e\u52a0\u7528\u4e8e\u5f80form\u91cc\u6dfb\u52a0grid\u7ec4\u4ef6\uff0c\u7528\u4e8e\u4e00\u8d77\u63d0\u4ea4\u6570\u636e\uff0c\u8c22\u56fd\u94a7
	 */
	pushGrid : function(obj) {

		if (obj instanceof Array) {
			for (var i = 0; i < obj.length; ++i) {
				var grid = obj[i];
				// if(grid instanceof Ext.grid.EditorGridPanel){
				this.gridArray.push(grid);
				// }
			}
		} else {
			// if(obj instanceof Ext.grid.EditorGridPanel){
			this.gridArray.push(obj);
			return;
			// }
		}
	},
	getGridArray : function() {
		return this.gridArray;
	}
});
Ext.reg('htmlform', Wonders.form.HtmlForm);

/*******************************************************************************
 * 第三方组件引入
 ******************************************************************************/

/**
 * @ignore Ext.DatePicker Ext.Component Simple date picker class.
 * 
 * Create a new DatePicker {Object} config The config object
 */
Ext.DatePicker = Ext
		.extend(
				Ext.Component,
				{
					/**
					 * cfg {String} todayText The text to display on the button
					 * that selects the current date (defaults to "Today")
					 */
					todayText : "\u4eca\u5929",
					/**
					 * cfg {String} okText The text to display on the ok button
					 */
					okText : "\u786e\u5b9a", // &#160; to give the user extra
												// clicking room
					/**
					 * cfg {String} cancelText The text to display on the cancel
					 * button
					 */
					cancelText : "\u53d6\u6d88",
					/**
					 * cfg {String} todayTip The tooltip to display for the
					 * button that selects the current date (defaults to
					 * "{current date} (Spacebar)")
					 */
					todayTip : "{0} (Spacebar)",
					/**
					 * cfg {String} minText The error text to display if the
					 * minDate validation fails (defaults to "This date is
					 * before the minimum date")
					 */
					minText : "\u5f53\u524d\u65e5\u671f\u4e0d\u80fd\u5728\u6700\u5c0f\u65e5\u671f\u4e4b\u524d",
					/**
					 * cfg {String} maxText The error text to display if the
					 * maxDate validation fails (defaults to "This date is after
					 * the maximum date")
					 */
					maxText : "\u5f53\u524d\u65e5\u671f\u4e0d\u80fd\u5728\u6700\u5927\u65e5\u671f\u4e4b\u540e",
					/**
					 * cfg {String} format The default date format string which
					 * can be overriden for localization support. The format
					 * must be valid according to {link Date#parseDate}
					 * (defaults to 'm/d/y').
					 */
					format : "m/d/y",
					/**
					 * cfg {String} disabledDaysText The tooltip to display when
					 * the date falls on a disabled day (defaults to "Disabled")
					 */
					disabledDaysText : "Disabled",
					/**
					 * cfg {String} disabledDatesText The tooltip text to
					 * display when the date falls on a disabled date (defaults
					 * to "Disabled")
					 */
					disabledDatesText : "Disabled",
					/**
					 * cfg {Boolean} constrainToViewport <b>Deprecated</b> (not
					 * currently used). True to constrain the date picker to the
					 * viewport (defaults to true)
					 */
					constrainToViewport : true,
					/**
					 * cfg {Array} monthNames An array of textual month names
					 * which can be overriden for localization support (defaults
					 * to Date.monthNames)
					 */
					monthNames : Date.monthNames,
					/**
					 * cfg {Array} dayNames An array of textual day names which
					 * can be overriden for localization support (defaults to
					 * Date.dayNames)
					 */
					dayNames : Date.dayNames,
					/**
					 * cfg {String} nextText The next month navigation button
					 * tooltip (defaults to 'Next Month (Control+Right)')
					 */
					nextText : '\u4e0b\u4e00\u4e2a\u6708 (Control+Right)',
					/**
					 * cfg {String} prevText The previous month navigation
					 * button tooltip (defaults to 'Previous Month
					 * (Control+Left)')
					 */
					prevText : '\u524d\u4e00\u4e2a\u6708 (Control+Left)',
					/**
					 * cfg {String} monthYearText The header month selector
					 * tooltip (defaults to 'Choose a month (Control+Up/Down to
					 * move years)')
					 */
					monthYearText : '\u9009\u62e9\u6708\u4efd (Control+Up/Down to move years)',
					/**
					 * cfg {Number} startDay Day index at which the week should
					 * begin, 0-based (defaults to 0, which is Sunday)
					 */
					startDay : 0,
					/**
					 * cfg {Boolean} showToday False to hide the footer area
					 * containing the Today button and disable the keyboard
					 * handler for spacebar that selects the current date
					 * (defaults to true).
					 */
					showToday : true,
					/**
					 * cfg {Date} minDate Minimum allowable date (JavaScript
					 * date object, defaults to null)
					 */
					/**
					 * cfg {Date} maxDate Maximum allowable date (JavaScript
					 * date object, defaults to null)
					 */
					/**
					 * cfg {Array} disabledDays An array of days to disable,
					 * 0-based. For example, [0, 6] disables Sunday and Saturday
					 * (defaults to null).
					 */
					/**
					 * cfg {RegExp} disabledDatesRE JavaScript regular
					 * expression used to disable a pattern of dates (defaults
					 * to null). The {link #disabledDates} config will generate
					 * this regex internally, but if you specify disabledDatesRE
					 * it will take precedence over the disabledDates value.
					 */
					/**
					 * cfg {Array} disabledDates An array of "dates" to disable,
					 * as strings. These strings will be used to build a dynamic
					 * regular expression so they are very powerful. Some
					 * examples:
					 * <ul>
					 * <li>["03/08/2003", "09/16/2003"] would disable those
					 * exact dates</li>
					 * <li>["03/08", "09/16"] would disable those days for
					 * every year</li>
					 * <li>["^03/08"] would only match the beginning (useful if
					 * you are using short years)</li>
					 * <li>["03/../2006"] would disable every day in March 2006</li>
					 * <li>["^03"] would disable every day in every March</li>
					 * </ul>
					 * Note that the format of the dates included in the array
					 * should exactly match the {link #format} config. In order
					 * to support regular expressions, if you are using a date
					 * format that has "." in it, you will have to escape the
					 * dot when restricting dates. For example:
					 * ["03\\.08\\.03"].
					 */

					// private
					initComponent : function() {
						Ext.DatePicker.superclass.initComponent.call(this);

						this.value = this.value ? this.value.clearTime()
								: getServerTime().clearTime();

						this.addEvents(
						/**
						 * event select Fires when a date is selected param
						 * {DatePicker} this param {Date} date The selected date
						 */
						'select');

						if (this.handler) {
							this.on("select", this.handler, this.scope || this);
						}

						this.initDisabledDays();
					},

					// private
					initDisabledDays : function() {
						if (!this.disabledDatesRE && this.disabledDates) {
							var dd = this.disabledDates;
							var re = "(?:";
							for (var i = 0; i < dd.length; i++) {
								re += dd[i];
								if (i != dd.length - 1)
									re += "|";
							}
							this.disabledDatesRE = new RegExp(re + ")");
						}
					},

					/**
					 * Replaces any existing disabled dates with new values and
					 * refreshes the DatePicker. param {Array/RegExp}
					 * disabledDates An array of date strings (see the {link
					 * #disabledDates} config for details on supported values),
					 * or a JavaScript regular expression used to disable a
					 * pattern of dates.
					 */
					setDisabledDates : function(dd) {
						if (Ext.isArray(dd)) {
							this.disabledDates = dd;
							this.disabledDatesRE = null;
						} else {
							this.disabledDatesRE = dd;
						}
						this.initDisabledDays();
						this.update(this.value, true);
					},

					/**
					 * Replaces any existing disabled days (by index, 0-6) with
					 * new values and refreshes the DatePicker. param {Array}
					 * disabledDays An array of disabled day indexes. See the
					 * {link #disabledDays} config for details on supported
					 * values.
					 */
					setDisabledDays : function(dd) {
						this.disabledDays = dd;
						this.update(this.value, true);
					},

					/**
					 * Replaces any existing {link #minDate} with the new value
					 * and refreshes the DatePicker. param {Date} value The
					 * minimum date that can be selected
					 */
					setMinDate : function(dt) {
						this.minDate = dt;
						this.update(this.value, true);
					},

					/**
					 * Replaces any existing {link #maxDate} with the new value
					 * and refreshes the DatePicker. param {Date} value The
					 * maximum date that can be selected
					 */
					setMaxDate : function(dt) {
						this.maxDate = dt;
						this.update(this.value, true);
					},

					/**
					 * Sets the value of the date field param {Date} value The
					 * date to set
					 */
					setValue : function(value) {
						var old = this.value;
						this.value = value.clearTime(true);
						if (this.el) {
							this.update(this.value);
						}
					},

					/**
					 * Gets the current selected value of the date field return
					 * {Date} The selected date
					 */
					getValue : function() {
						return this.value;
					},

					// private
					focus : function() {
						if (this.el) {
							this.update(this.activeDate);
						}
					},

					// private
					onRender : function(container, position) {
						var m = [
								'<table cellspacing="0">',
								'<tr><td class="x-date-left"><a href="#" title="',
								this.prevText,
								'">&#160;</a></td><td class="x-date-middle" align="center"></td><td class="x-date-right"><a href="#" title="',
								this.nextText,
								'">&#160;</a></td></tr>',
								'<tr id="date_days"><td colspan="3"><table class="x-date-inner" cellspacing="0"><thead><tr>' ];
						var dn = this.dayNames;
						for (var i = 0; i < 7; i++) {
							var d = this.startDay + i;
							if (d > 6) {
								d = d - 7;
							}
							m.push("<th><span>", dn[d].substr(dn[d].length - 1,
									1), "</span></th>");
						}
						m[m.length] = "</tr></thead><tbody><tr>";
						for (var i = 0; i < 42; i++) {
							if (i % 7 == 0 && i != 0) {
								m[m.length] = "</tr><tr>";
							}
							m[m.length] = '<td><a href="#" hidefocus="on" class="x-date-date" tabIndex="1"><em><span></span></em></a></td>';
						}
						m
								.push(
										'</tr></tbody></table></td></tr>',
										this.showToday ? '<tr id="date_bottom"><td colspan="3" class="x-date-bottom" align="center"></td></tr>'
												: '',
										'</table><div class="x-date-mp"></div>');

						var el = document.createElement("div");
						el.className = "x-date-picker";
						el.innerHTML = m.join("");

						container.dom.insertBefore(el, position);

						this.el = Ext.get(el);
						this.eventEl = Ext.get(el.firstChild);

						new Ext.util.ClickRepeater(this.el
								.child("td.x-date-left a"), {
							handler : this.showPrevMonth,
							scope : this,
							preventDefault : true,
							stopDefault : true
						});

						new Ext.util.ClickRepeater(this.el
								.child("td.x-date-right a"), {
							handler : this.showNextMonth,
							scope : this,
							preventDefault : true,
							stopDefault : true
						});

						this.eventEl.on("mousewheel", this.handleMouseWheel,
								this);

						this.monthPicker = this.el.down('div.x-date-mp');
						this.monthPicker.enableDisplayMode('block');

						var kn = new Ext.KeyNav(this.eventEl, {
							"left" : function(e) {
								e.ctrlKey ? this.showPrevMonth() : this
										.update(this.activeDate.add("d", -1));
							},

							"right" : function(e) {
								e.ctrlKey ? this.showNextMonth() : this
										.update(this.activeDate.add("d", 1));
							},

							"up" : function(e) {
								e.ctrlKey ? this.showNextYear() : this
										.update(this.activeDate.add("d", -7));
							},

							"down" : function(e) {
								e.ctrlKey ? this.showPrevYear() : this
										.update(this.activeDate.add("d", 7));
							},

							"pageUp" : function(e) {
								this.showNextMonth();
							},

							"pageDown" : function(e) {
								this.showPrevMonth();
							},

							"enter" : function(e) {
								e.stopPropagation();
								return true;
							},

							scope : this
						});

						this.eventEl.on("click", this.handleDateClick, this, {
							delegate : "a.x-date-date"
						});

						this.el.unselectable();

						this.cells = this.el
								.select("table.x-date-inner tbody td");
						this.textNodes = this.el
								.query("table.x-date-inner tbody span");

						this.mbtn = new Ext.Button({
							text : "&#160;",
							tooltip : this.monthYearText,
							renderTo : this.el.child("td.x-date-middle", true)
						});

						this.mbtn.on('click', this.showMonthPicker, this);
						this.mbtn.el.child(this.mbtn.menuClassTarget).addClass(
								"x-btn-with-menu");

						if (this.showToday) {
							this.todayKeyListener = this.eventEl
									.addKeyListener(Ext.EventObject.SPACE,
											this.selectToday, this);
							var today = (getServerTime())
									.dateFormat(this.format);
							this.todayBtn = new Ext.Button({
								renderTo : this.el.child("td.x-date-bottom",
										true),
								text : String.format(this.todayText, today),
								tooltip : String.format(this.todayTip, today),
								handler : this.selectToday,
								scope : this
							});
						}

						if (Ext.isIE) {
							this.el.repaint();
						}

						this.update(this.value);
						// --xuke
						if (this.format.indexOf('d') == -1) {
							// Ext.get('date_days').hide();
							// Ext.get('date_bottom').hide();
							this.el.select("table.x-date-inner").hide();
							this.el.child("td.x-date-bottom").hide();
						}
					},

					// private
					createMonthPicker : function() {
						if (!this.monthPicker.dom.firstChild) {
							var buf = [ '<table border="0" cellspacing="0">' ];
							for (var i = 0; i < 6; i++) {
								buf
										.push(
												'<tr><td class="x-date-mp-month"><a href="#">',
												this.monthNames[i].substr(0, 3),
												'</a></td>',
												'<td class="x-date-mp-month x-date-mp-sep"><a href="#">',
												this.monthNames[i + 6].substr(
														0, 3),
												'</a></td>',
												i == 0 ? '<td class="x-date-mp-ybtn" align="center"><a class="x-date-mp-prev"></a></td><td class="x-date-mp-ybtn" align="center"><a class="x-date-mp-next"></a></td></tr>'
														: '<td class="x-date-mp-year"><a href="#"></a></td><td class="x-date-mp-year"><a href="#"></a></td></tr>');
							}
							buf
									.push(
											'<tr class="x-date-mp-btns"><td colspan="4"><button type="button" class="x-date-mp-ok">',
											this.okText,
											'</button><button type="button" class="x-date-mp-cancel">',
											this.cancelText,
											'</button></td></tr>', '</table>');
							this.monthPicker.update(buf.join(''));
							this.monthPicker.on('click', this.onMonthClick,
									this);
							this.monthPicker.on('dblclick',
									this.onMonthDblClick, this);

							this.mpMonths = this.monthPicker
									.select('td.x-date-mp-month');
							this.mpYears = this.monthPicker
									.select('td.x-date-mp-year');

							this.mpMonths.each(function(m, a, i) {
								i += 1;
								if ((i % 2) == 0) {
									m.dom.xmonth = 5 + Math.round(i * .5);
								} else {
									m.dom.xmonth = Math.round((i - 1) * .5);
								}
							});
						}
					},

					// private
					showMonthPicker : function() {
						this.createMonthPicker();
						var size = this.el.getSize();
						this.monthPicker.setSize(size);
						this.monthPicker.child('table').setSize(size);

						this.mpSelMonth = (this.activeDate || this.value)
								.getMonth();
						this.updateMPMonth(this.mpSelMonth);
						this.mpSelYear = (this.activeDate || this.value)
								.getFullYear();
						this.updateMPYear(this.mpSelYear);

						this.monthPicker.slideIn('t', {
							duration : .2
						});
					},

					// private
					updateMPYear : function(y) {
						this.mpyear = y;
						var ys = this.mpYears.elements;
						for (var i = 1; i <= 10; i++) {
							var td = ys[i - 1], y2;
							if ((i % 2) == 0) {
								y2 = y + Math.round(i * .5);
								td.firstChild.innerHTML = y2;
								td.xyear = y2;
							} else {
								y2 = y - (5 - Math.round(i * .5));
								td.firstChild.innerHTML = y2;
								td.xyear = y2;
							}
							this.mpYears.item(i - 1)[y2 == this.mpSelYear ? 'addClass'
									: 'removeClass']('x-date-mp-sel');
						}
					},

					// private
					updateMPMonth : function(sm) {
						this.mpMonths.each(function(m, a, i) {
							m[m.dom.xmonth == sm ? 'addClass' : 'removeClass']
									('x-date-mp-sel');
						});
					},

					// private
					selectMPMonth : function(m) {

					},

					// private
					onMonthClick : function(e, t) {
						e.stopEvent();
						var el = new Ext.Element(t), pn;
						if (el.is('button.x-date-mp-cancel')) {
							this.hideMonthPicker();
							// --xuke
							if (this.format.indexOf('d') == -1) {
								this.menu.hide();
							}
						} else if (el.is('button.x-date-mp-ok')) {
							var d = new Date(this.mpSelYear, this.mpSelMonth,
									(this.activeDate || this.value).getDate());
							if (d.getMonth() != this.mpSelMonth) {
								// "fix" the JS rolling date conversion if
								// needed
								d = new Date(this.mpSelYear, this.mpSelMonth, 1)
										.getLastDateOfMonth();
							}
							// force update
							this.update(d, true);
							this.hideMonthPicker();
							// --xuke
							if (this.format.indexOf('d') == -1) {
								this.setValue(d);
								this.menu.hide();
							}
						} else if (pn = el.up('td.x-date-mp-month', 2)) {
							this.mpMonths.removeClass('x-date-mp-sel');
							pn.addClass('x-date-mp-sel');
							this.mpSelMonth = pn.dom.xmonth;
						} else if (pn = el.up('td.x-date-mp-year', 2)) {
							this.mpYears.removeClass('x-date-mp-sel');
							pn.addClass('x-date-mp-sel');
							this.mpSelYear = pn.dom.xyear;
						} else if (el.is('a.x-date-mp-prev')) {
							this.updateMPYear(this.mpyear - 10);
						} else if (el.is('a.x-date-mp-next')) {
							this.updateMPYear(this.mpyear + 10);
						}
					},

					// private
					onMonthDblClick : function(e, t) {
						e.stopEvent();
						var el = new Ext.Element(t), pn;
						if (pn = el.up('td.x-date-mp-month', 2)) {
							var d = new Date(this.mpSelYear, this.mpSelMonth,
									(this.activeDate || this.value).getDate());
							if (d.getMonth() != this.mpSelMonth) {
								// "fix" the JS rolling date conversion if
								// needed
								d = new Date(this.mpSelYear, this.mpSelMonth, 1)
										.getLastDateOfMonth();
							}
							// force update
							this.update(d, true);
							this.hideMonthPicker();
							// --xuke
							if (this.format.indexOf('d') == -1) {
								this.setValue(new Date(this.mpSelYear,
										pn.dom.xmonth,
										(this.activeDate || this.value)
												.getDate()));
								this.menu.hide();
							}
						} else if (pn = el.up('td.x-date-mp-year', 2)) {
							// force update
							this.update(new Date(pn.dom.xyear, this.mpSelMonth,
									(this.activeDate || this.value).getDate()),
									true);
							this.hideMonthPicker();
							// --xuke
							if (this.format.indexOf('d') == -1) {
								this.setValue(new Date(pn.dom.xyear,
										this.mpSelMonth,
										(this.activeDate || this.value)
												.getDate()));
								this.menu.hide();
							}
						}
					},

					// private
					hideMonthPicker : function(disableAnim) {
						if (this.monthPicker) {
							if (disableAnim === true) {
								this.monthPicker.hide();
							} else {
								this.monthPicker.slideOut('t', {
									duration : .2
								});
							}
						}
					},

					// private
					showPrevMonth : function(e) {
						this.update(this.activeDate.add("mo", -1));
					},

					// private
					showNextMonth : function(e) {
						this.update(this.activeDate.add("mo", 1));
					},

					// private
					showPrevYear : function() {
						this.update(this.activeDate.add("y", -1));
					},

					// private
					showNextYear : function() {
						this.update(this.activeDate.add("y", 1));
					},

					// private
					handleMouseWheel : function(e) {
						var delta = e.getWheelDelta();
						if (delta > 0) {
							this.showPrevMonth();
							e.stopEvent();
						} else if (delta < 0) {
							this.showNextMonth();
							e.stopEvent();
						}
					},

					// private
					handleDateClick : function(e, t) {
						e.stopEvent();
						if (t.dateValue
								&& !Ext.fly(t.parentNode).hasClass(
										"x-date-disabled")) {
							this.setValue(new Date(t.dateValue));
							this.fireEvent("select", this, this.value);
						}
					},

					// private
					selectToday : function() {
						if (this.todayBtn && !this.todayBtn.disabled) {
							this.setValue(getServerTime().clearTime());
							this.fireEvent("select", this, this.value);
						}
					},

					// private
					update : function(date, forceRefresh) {
						var vd = this.activeDate;
						this.activeDate = date;
						if (!forceRefresh && vd && this.el) {
							var t = date.getTime();
							if (vd.getMonth() == date.getMonth()
									&& vd.getFullYear() == date.getFullYear()) {
								this.cells.removeClass("x-date-selected");
								this.cells.each(function(c) {
									if (c.dom.firstChild.dateValue == t) {
										c.addClass("x-date-selected");
										setTimeout(function() {
											try {
												c.dom.firstChild.focus();
											} catch (e) {
											}
										}, 50);
										return false;
									}
								});
								return;
							}
						}
						var days = date.getDaysInMonth();
						var firstOfMonth = date.getFirstDateOfMonth();
						var startingPos = firstOfMonth.getDay() - this.startDay;

						if (startingPos <= this.startDay) {
							startingPos += 7;
						}

						var pm = date.add("mo", -1);
						var prevStart = pm.getDaysInMonth() - startingPos;

						var cells = this.cells.elements;
						var textEls = this.textNodes;
						days += startingPos;

						// convert everything to numbers so it's fast
						var day = 86400000;
						var d = (new Date(pm.getFullYear(), pm.getMonth(),
								prevStart)).clearTime();
						var today = getServerTime().clearTime().getTime();
						var sel = date.clearTime().getTime();
						var min = this.minDate ? this.minDate.clearTime()
								: Number.NEGATIVE_INFINITY;
						var max = this.maxDate ? this.maxDate.clearTime()
								: Number.POSITIVE_INFINITY;
						var ddMatch = this.disabledDatesRE;
						var ddText = this.disabledDatesText;
						var ddays = this.disabledDays ? this.disabledDays
								.join("") : false;
						var ddaysText = this.disabledDaysText;
						var format = this.format;

						if (this.showToday) {
							var td = getServerTime().clearTime();
							var disable = (td < min
									|| td > max
									|| (ddMatch && format && ddMatch.test(td
											.dateFormat(format))) || (ddays && ddays
									.indexOf(td.getDay()) != -1));

							this.todayBtn.setDisabled(disable);
							this.todayKeyListener[disable ? 'disable'
									: 'enable']();
						}
						/**
						 * @ignore
						 */
						var setCellClass = function(cal, cell) {
							cell.title = "";
							var t = d.getTime();
							cell.firstChild.dateValue = t;
							if (t == today) {
								cell.className += " x-date-today";
								cell.title = cal.todayText;
							}
							if (t == sel) {
								cell.className += " x-date-selected";
								setTimeout(function() {
									try {
										cell.firstChild.focus();
									} catch (e) {
									}
								}, 50);
							}
							// disabling
							if (t < min) {
								cell.className = " x-date-disabled";
								cell.title = cal.minText;
								return;
							}
							if (t > max) {
								cell.className = " x-date-disabled";
								cell.title = cal.maxText;
								return;
							}
							if (ddays) {
								if (ddays.indexOf(d.getDay()) != -1) {
									cell.title = ddaysText;
									cell.className = " x-date-disabled";
								}
							}
							if (ddMatch && format) {
								var fvalue = d.dateFormat(format);
								if (ddMatch.test(fvalue)) {
									cell.title = ddText.replace("%0", fvalue);
									cell.className = " x-date-disabled";
								}
							}
						};

						var i = 0;
						for (; i < startingPos; i++) {
							textEls[i].innerHTML = (++prevStart);
							d.setDate(d.getDate() + 1);
							cells[i].className = "x-date-prevday";
							setCellClass(this, cells[i]);
						}
						for (; i < days; i++) {
							intDay = i - startingPos + 1;
							textEls[i].innerHTML = (intDay);
							d.setDate(d.getDate() + 1);
							cells[i].className = "x-date-active";
							setCellClass(this, cells[i]);
						}
						var extraDays = 0;
						for (; i < 42; i++) {
							textEls[i].innerHTML = (++extraDays);
							d.setDate(d.getDate() + 1);
							cells[i].className = "x-date-nextday";
							setCellClass(this, cells[i]);
						}
						// xuke
						if (this.format.indexOf('d') == -1
								&& this.getValue() != date) {
							this.input.setValue(date);
							// this.input.fireEvent("select", date, this.input);
							this.input.fireEvent("select", this, this.value);
						}

						this.mbtn.setText(this.monthNames[date.getMonth()]
								+ " " + date.getFullYear());

						if (!this.internalRender) {
							var main = this.el.dom.firstChild;
							var w = main.offsetWidth;
							this.el.setWidth(w + this.el.getBorderWidth("lr"));
							Ext.fly(main).setWidth(w);
							this.internalRender = true;
							// opera does not respect the auto grow header
							// center column
							// then, after it gets a width opera refuses to
							// recalculate
							// without a second pass
							if (Ext.isOpera && !this.secondPass) {
								main.rows[0].cells[1].style.width = (w - (main.rows[0].cells[0].offsetWidth + main.rows[0].cells[2].offsetWidth))
										+ "px";
								this.secondPass = true;
								this.update.defer(10, this, [ date ]);
							}
						}
					},

					// private
					beforeDestroy : function() {
						if (this.rendered) {
							Ext.destroy(this.mbtn, this.todayBtn);
						}
					}

				/**
				 * cfg {String} autoEl hide
				 */
				});
Ext.reg('datepicker', Ext.DatePicker);

/**
 * @ignore Ext.ux.form.DateTime extends Ext.form.Field
 * 
 * DateTime field, combination of DateField and TimeField
 * 
 * Creates new DateTime constructor param {Object} config A config object
 */
Ext.ux.form.DateTime = Ext
		.extend(
				Ext.form.Field,
				{
					/**
					 * cfg {Function} dateValidator A custom validation function
					 * to be called during date field validation (defaults to
					 * null)
					 */
					dateValidator : null
					/**
					 * cfg {String/Object} defaultAutoCreate DomHelper element
					 * spec Let superclass to create hidden field instead of
					 * textbox. Hidden will be submittend to server
					 */
					,
					defaultAutoCreate : {
						tag : 'input',
						type : 'hidden'
					}
					/**
					 * cfg {String} dtSeparator Date - Time separator. Used to
					 * split date and time (defaults to ' ' (space))
					 */
					,
					dtSeparator : ' '
					/**
					 * cfg {String} hiddenFormat Format of datetime used to
					 * store value in hidden field and submitted to server
					 * (defaults to 'Y-m-d H:i:s' that is mysql format)
					 */
					,
					hiddenFormat : 'Y-m-d H:i:s'
					/**
					 * cfg {Boolean} otherToNow Set other field to now() if not
					 * explicly filled in (defaults to true)
					 */
					,
					otherToNow : true
					/**
					 * cfg {Boolean} emptyToNow Set field value to now on
					 * attempt to set empty value. If it is true then setValue()
					 * sets value of field to current date and time (defaults to
					 * false)
					 */
					/**
					 * cfg {String} timePosition Where the time field should be
					 * rendered. 'right' is suitable for forms and 'below' is
					 * suitable if the field is used as the grid editor
					 * (defaults to 'right')
					 */
					,
					timePosition : 'right' // valid values:'below', 'right'
					/**
					 * cfg {Function} timeValidator A custom validation function
					 * to be called during time field validation (defaults to
					 * null)
					 */
					,
					timeValidator : null

					/**
					 * cfg {Integer} defaultWidth A default width for both
					 * datefield and timefield
					 */
					,
					defaultWidth : 100
					/**
					 * cfg {Integer} timeWidth width for timefield
					 */
					,
					timeWidth : null
					/**
					 * cfg {Integer} dateWidth width for datefield
					 */
					,
					dateWidth : null
					/**
					 * cfg {Object} dateConfig Config for DateField constructor.
					 */
					/**
					 * cfg {Object} timeConfig Config for TimeField constructor.
					 */

					// {{{
					/**
					 * private creates DateField and TimeField and installs the
					 * necessary event handlers
					 */
					,
					initComponent : function() {
						// call parent initComponent
						Ext.ux.form.DateTime.superclass.initComponent
								.call(this);
						// create DateField
						var dateConfig = Ext.apply({}, {
							id : this.id + '-date',
							format : this.dateFormat
									|| Ext.form.DateField.prototype.format,
							selectOnFocus : this.selectOnFocus,
							validator : this.dateValidator,
							readOnly : this.readOnly,
							disabled : this.disabled,
							width : this.dateWidth,
							tabIndex : this.tabIndex,
							listeners : {
								blur : {
									scope : this,
									fn : this.onBlur
								},
								focus : {
									scope : this,
									fn : this.onFocus
								}
							}
						}, this.dateConfig);
						if (!dateConfig.width) {
							dateConfig.width = this.defaultWidth;
						}
						this.df = new Ext.form.DateField(dateConfig);
						this.df.ownerCt = this;
						delete (this.dateFormat);

						// create TimeField
						var timeConfig = Ext.apply({}, {
							id : this.id + '-time',
							format : this.timeFormat
									|| Ext.form.TimeField.prototype.format,
							selectOnFocus : this.selectOnFocus,
							validator : this.timeValidator,
							readOnly : this.readOnly,
							disabled : this.disabled,
							width : this.timeWidth,
							tabIndex : this.tabIndex,
							listeners : {
								blur : {
									scope : this,
									fn : this.onBlur
								},
								focus : {
									scope : this,
									fn : this.onFocus
								}
							}
						}, this.timeConfig);
						if (!timeConfig.width) {
							timeConfig.width = this.defaultWidth;
						}
						this.tf = new Ext.form.TimeField(timeConfig);
						this.tf.ownerCt = this;
						delete (this.timeFormat);

						// relay events
						this.relayEvents(this.df, [ 'focus', 'specialkey',
								'invalid', 'valid' ]);
						this.relayEvents(this.tf, [ 'focus', 'specialkey',
								'invalid', 'valid' ]);
						this.setValue(this.value);

					} // eo function initComponent
					// }}}
					// {{{
					/**
					 * private Renders underlying DateField and TimeField and
					 * provides a workaround for side error icon bug
					 */
					,
					onRender : function(ct, position) {
						if (this.df.readOnly) {
							this.df.hideTrigger = true;
						}
						// don't run more than once
						if (this.isRendered) {
							return;
						}

						// render underlying hidden field
						Ext.ux.form.DateTime.superclass.onRender.call(this, ct,
								position);

						// render DateField and TimeField
						// create bounding table
						var t;
						if ('below' === this.timePosition
								|| 'bellow' === this.timePosition) {
							t = Ext.DomHelper.append(ct, {
								tag : 'table',
								style : 'border-collapse:collapse',
								children : [ {
									tag : 'tr',
									children : [ {
										tag : 'td',
										style : 'padding-bottom:1px',
										cls : 'ux-datetime-date'
									} ]
								}, {
									tag : 'tr',
									children : [ {
										tag : 'td',
										cls : 'ux-datetime-time'
									} ]
								} ]
							}, true);
						} else {
							t = Ext.DomHelper.append(ct, {
								tag : 'table',
								style : 'border-collapse:collapse',
								children : [ {
									tag : 'tr',
									children : [ {
										tag : 'td',
										style : 'padding-right:4px',
										cls : 'ux-datetime-date'
									}, {
										tag : 'td',
										cls : 'ux-datetime-time'
									} ]
								} ]
							}, true);
						}

						this.tableEl = t;
						this.wrap = t.wrap({
							cls : 'x-form-field-wrap'
						});
						// this.wrap = t.wrap();
						this.wrap.on("mousedown", this.onMouseDown, this, {
							delay : 10
						});

						// render DateField & TimeField
						this.df.render(t.child('td.ux-datetime-date'));
						this.tf.render(t.child('td.ux-datetime-time'));

						// workaround for IE trigger misalignment bug
						// see
						// http://extjs.com/forum/showthread.php?p=341075#post341075
						// if(Ext.isIE && Ext.isStrict) {
						// t.select('input').applyStyles({top:0});
						// }

						this.on('specialkey', this.onSpecialKey, this);
						this.df.el.swallowEvent([ 'keydown', 'keypress' ]);
						this.tf.el.swallowEvent([ 'keydown', 'keypress' ]);

						// create icon for side invalid errorIcon
						if ('side' === this.msgTarget) {
							var elp = this.el.findParent('.x-form-element', 10,
									true);
							this.errorIcon = elp.createChild({
								cls : 'x-form-invalid-icon'
							});

							var o = {
								errorIcon : this.errorIcon,
								msgTarget : 'side',
								alignErrorIcon : this.alignErrorIcon
										.createDelegate(this)
							};
							Ext.apply(this.df, o);
							Ext.apply(this.tf, o);
							// this.df.errorIcon = this.errorIcon;
							// this.tf.errorIcon = this.errorIcon;
						}

						// setup name for submit
						this.el.dom.name = this.hiddenName || this.name
								|| this.id;

						// prevent helper fields from being submitted
						this.df.el.dom.removeAttribute("name");
						this.tf.el.dom.removeAttribute("name");

						// we're rendered flag
						this.isRendered = true;

						// update hidden field
						this.updateHidden();

					} // eo function onRender
					// }}}
					// {{{
					/**
					 * private
					 */
					,
					adjustSize : Ext.BoxComponent.prototype.adjustSize
					// }}}
					// {{{
					/**
					 * private
					 */
					,
					alignErrorIcon : function() {
						this.errorIcon.alignTo(this.tableEl, 'tl-tr', [ 2, 0 ]);
					}
					// }}}
					// {{{
					/**
					 * private initializes internal dateValue
					 */
					,
					initDateValue : function() {
						this.dateValue = this.otherToNow ? getServerTime()
								: new Date(1970, 0, 1, 0, 0, 0);
					}
					// }}}
					// {{{
					/**
					 * Calls clearInvalid on the DateField and TimeField
					 */
					,
					clearInvalid : function() {
						this.df.clearInvalid();
						this.tf.clearInvalid();
					} // eo function clearInvalid
					// }}}
					// {{{
					/**
					 * Calls markInvalid on both DateField and TimeField param
					 * {String} msg Invalid message to display
					 */
					,
					markInvalid : function(msg) {
						this.df.markInvalid(msg);
						this.tf.markInvalid(msg);
					} // eo function markInvalid
					// }}}
					// {{{
					/**
					 * private called from Component::destroy. Destroys all
					 * elements and removes all listeners we've created.
					 */
					,
					beforeDestroy : function() {
						if (this.isRendered) {
							// this.removeAllListeners();
							this.wrap.removeAllListeners();
							this.wrap.remove();
							this.tableEl.remove();
							this.df.destroy();
							this.tf.destroy();
						}
					} // eo function beforeDestroy
					// }}}
					// {{{
					/**
					 * Disable this component. return {Ext.Component} this
					 */
					,
					disable : function() {
						if (this.isRendered) {
							this.df.disabled = this.disabled;
							this.df.onDisable();
							this.tf.onDisable();
						}
						this.disabled = true;
						this.df.disabled = true;
						this.tf.disabled = true;
						this.fireEvent("disable", this);
						return this;
					} // eo function disable
					// }}}
					// {{{
					/**
					 * Enable this component. return {Ext.Component} this
					 */
					,
					enable : function() {
						if (this.rendered) {
							this.df.onEnable();
							this.tf.onEnable();
						}
						this.disabled = false;
						this.df.disabled = false;
						this.tf.disabled = false;
						this.fireEvent("enable", this);
						return this;
					} // eo function enable
					// }}}
					// {{{
					/**
					 * private Focus date filed
					 */
					,
					focus : function() {
						this.df.focus();
					} // eo function focus
					// }}}
					// {{{
					/**
					 * private
					 */
					,
					getPositionEl : function() {
						return this.wrap;
					}
					// }}}
					// {{{
					/**
					 * private
					 */
					,
					getResizeEl : function() {
						return this.wrap;
					}
					// }}}
					// {{{
					/**
					 * return {Date/String} Returns value of this field
					 */
					,
					getValue : function() {
						// create new instance of date
						return this.dateValue ? new Date(this.dateValue) : '';
					} // eo function getValue
					// }}}
					// {{{
					/**
					 * return {Boolean} true = valid, false = invalid private
					 * Calls isValid methods of underlying DateField and
					 * TimeField and returns the result
					 */
					,
					isValid : function() {
						return this.df.isValid() && this.tf.isValid();
					} // eo function isValid
					// }}}
					// {{{
					/**
					 * Returns true if this component is visible return
					 * {boolean}
					 */
					,
					isVisible : function() {
						return this.df.rendered
								&& this.df.getActionEl().isVisible();
					} // eo function isVisible
					// }}}
					// {{{
					/**
					 * private Handles blur event
					 */
					,
					onBlur : function(f) {
						// called by both DateField and TimeField blur events

						// revert focus to previous field if clicked in between
						if (this.wrapClick) {
							f.focus();
							this.wrapClick = false;
						}

						// update underlying value
						if (f === this.df) {
							this.updateDate();
						} else {
							this.updateTime();
						}
						this.updateHidden();
						// fire events later
						(function() {
							if (!this.df.hasFocus && !this.tf.hasFocus) {
								var v = this.getValue();
								if (String(v) !== String(this.startValue)) {
									this.fireEvent("change", this, v,
											this.startValue);
								}
								this.hasFocus = false;
								this.fireEvent('blur', this);
							}
						}).defer(100, this);

					} // eo function onBlur
					// }}}
					// {{{
					/**
					 * private Handles focus event
					 */
					,
					onFocus : function() {
						if (!this.hasFocus) {
							this.hasFocus = true;
							this.startValue = this.getValue();
							this.fireEvent("focus", this);
						}
					}
					// }}}
					// {{{
					/**
					 * private Just to prevent blur event when clicked in the
					 * middle of fields
					 */
					,
					onMouseDown : function(e) {
						if (!this.disabled) {
							this.wrapClick = 'td' === e.target.nodeName
									.toLowerCase();
						}
					}
					// }}}
					// {{{
					/**
					 * private Handles Tab and Shift-Tab events
					 */
					,
					onSpecialKey : function(t, e) {
						var key = e.getKey();
						if (key === e.TAB) {
							if (t === this.df && !e.shiftKey) {
								e.stopEvent();
								this.tf.focus();
							}
							if (t === this.tf && e.shiftKey) {
								e.stopEvent();
								this.df.focus();
							}
						}
						// otherwise it misbehaves in editor grid
						if (key === e.ENTER) {
							this.updateValue();
						}

					} // eo function onSpecialKey
					// }}}
					// {{{
					/**
					 * Resets the current field value to the originally loaded
					 * value and clears any validation messages. See
					 * Ext.form.BasicForm.trackResetOnLoad
					 */
					,
					reset : function() {
						this.df.reset();
						this.tf.reset();
					} // eo function reset
					// }}}
					// {{{
					/**
					 * private Sets the value of DateField
					 */
					,
					setDate : function(date) {
						this.df.setValue(date);
					} // eo function setDate
					// }}}
					// {{{
					/**
					 * private Sets the value of TimeField
					 */
					,
					setTime : function(date) {
						this.tf.setValue(date);
					} // eo function setTime
					// }}}
					// {{{
					/**
					 * private Sets correct sizes of underlying DateField and
					 * TimeField With workarounds for IE bugs
					 */
					,
					setSize : function(w, h) {
						if (!w) {
							return;
						}
						if ('below' === this.timePosition) {
							this.df.setSize(w, h);
							this.tf.setSize(w, h);
							if (Ext.isIE) {
								this.df.el.up('td').setWidth(w);
								this.tf.el.up('td').setWidth(w);
							}
						} else {
							if (w < 2 * this.defaultWidth + 4) {
								w = 2 * this.defaultWidth + 4;
							}
							var dfWidth = this.dateWidth, tfWidth = this.timeWidth;
							// 设置time width，却未设置date width
							if (!dfWidth && tfWidth) {
								dfWidth = w - tfWidth - 4;
							}
							// 设置date width，却未设置time width
							if (!tfWidth && dfWidth) {
								tfWidth = w - dfWidth - 4;
							}
							// 未设置date width，time width
							if (!dfWidth && !tfWidth) {
								dfWidth = tfWidth = (w - 4) / 2;
							}
							this.df.setSize(dfWidth, h);
							this.tf.setSize(tfWidth, h);
							
							// huyunming20160630设置日期时间间隔
							//document.getElementById(this.df.id).style.paddingRight = "0px";
							//document.getElementById(this.df.id).style.paddingLeft = "2px";
							//--
							
							if (Ext.isIE) {
								this.df.el.up('td').setWidth(dfWidth);
								this.tf.el.up('td').setWidth(tfWidth);
							}
						}
					} // eo function setSize
					// }}}
					// {{{
					/**
					 * param {Mixed} val Value to set Sets the value of this
					 * field
					 */
					,
					setValue : function(val) {
						if (!val && true === this.emptyToNow) {
							this.setValue(getServerTime());
							return;
						} else if (!val) {
							this.setDate('');
							this.setTime('');
							this.updateValue();
							return;
						}
						if ('number' === typeof val) {
							val = new Date(val);
						} else if ('string' === typeof val && this.hiddenFormat) {
							val = Date.parseDate(val, this.hiddenFormat);
						}
						val = val ? val : new Date(1970, 0, 1, 0, 0, 0);
						var da, time;
						if (val instanceof Date) {
							this.setDate(val);
							this.setTime(val);
							this.dateValue = new Date(Ext.isIE ? val.getTime()
									: val);
						} else {
							da = val.split(this.dtSeparator);
							this.setDate(da[0]);
							if (da[1]) {
								if (da[2]) {
									// add am/pm part back to time
									da[1] += da[2];
								}
								this.setTime(da[1]);
							}
						}
						this.updateValue();
					} // eo function setValue
					// }}}
					// {{{
					/**
					 * Hide or show this component by boolean return
					 * {Ext.Component} this
					 */
					,
					setVisible : function(visible) {
						if (visible) {
							this.df.show();
							this.tf.show();
						} else {
							this.df.hide();
							this.tf.hide();
						}
						return this;
					} // eo function setVisible
					// }}}
					// {{{
					,
					show : function() {
						return this.setVisible(true);
					} // eo function show
					// }}}
					// {{{
					,
					hide : function() {
						return this.setVisible(false);
					} // eo function hide
					// }}}
					// {{{
					/**
					 * private Updates the date part
					 */
					,
					updateDate : function() {

						var d = this.df.getValue();
						if (d) {
							if (!(this.dateValue instanceof Date)) {
								this.initDateValue();
								if (!this.tf.getValue()) {
									this.setTime(this.dateValue);
								}
							}
							this.dateValue.setMonth(0); // because of leap years
							this.dateValue.setFullYear(d.getFullYear());
							this.dateValue.setMonth(d.getMonth(), d.getDate());
							// this.dateValue.setDate(d.getDate());
						} else {
							this.dateValue = '';
							this.setTime('');
						}
					} // eo function updateDate
					// }}}
					// {{{
					/**
					 * private Updates the time part
					 */
					,
					updateTime : function() {
						var t = this.tf.getValue();
						if (t && !(t instanceof Date)) {
							t = Date.parseDate(t, this.tf.format);
						}
						if (t && !this.df.getValue()) {
							this.initDateValue();
							this.setDate(this.dateValue);
						}
						if (this.dateValue instanceof Date) {
							if (t) {
								this.dateValue.setHours(t.getHours());
								this.dateValue.setMinutes(t.getMinutes());
								this.dateValue.setSeconds(t.getSeconds());
							} else {
								this.dateValue.setHours(0);
								this.dateValue.setMinutes(0);
								this.dateValue.setSeconds(0);
							}
						}
					} // eo function updateTime
					// }}}
					// {{{
					/**
					 * private Updates the underlying hidden field value
					 */
					,
					updateHidden : function() {
						if (this.isRendered) {
							var value = this.dateValue instanceof Date ? this.dateValue
									.format(this.hiddenFormat)
									: '';
							this.el.dom.value = value;
						}
					}
					// }}}
					// {{{
					/**
					 * private Updates all of Date, Time and Hidden
					 */
					,
					updateValue : function() {

						this.updateDate();
						this.updateTime();
						this.updateHidden();

						return;
					} // eo function updateValue
					// }}}
					// {{{
					/**
					 * return {Boolean} true = valid, false = invalid calls
					 * validate methods of DateField and TimeField
					 */
					,
					validate : function() {
						return this.df.validate() && this.tf.validate();
					} // eo function validate
					// }}}
					// {{{
					/**
					 * Returns renderer suitable to render this field param
					 * {Object} Column model config
					 */
					,
					renderer : function(field) {
						var format = field.editor.dateFormat
								|| Ext.ux.form.DateTime.prototype.dateFormat;
						format += ' '
								+ (field.editor.timeFormat || Ext.ux.form.DateTime.prototype.timeFormat);
						/**
						 * @ignore
						 */
						var renderer = function(val) {
							var retval = Ext.util.Format.date(val, format);
							return retval;
						};
						return renderer;
					} // eo function renderer
				// }}}

				}); // eo extend

Ext.reg('xdatetime', Ext.ux.form.DateTime);

/**
 * @ignore Ext.ux.Spinner extends Ext.util.Observable Creates a Spinner control
 *         utilized by Ext.ux.form.SpinnerField
 * 
 * modified by Mitchell Simoens This modification was to allow the
 * Ext.ux.form.TimeField to allow the spinning of a 24 hour clock
 */
Ext.ux.Spinner = Ext
		.extend(
				Ext.util.Observable,
				{
					incrementValue : 1,
					alternateIncrementValue : 5,
					triggerClass : 'x-form-spinner-trigger',
					splitterClass : 'x-form-spinner-splitter',
					alternateKey : Ext.EventObject.shiftKey,
					defaultValue : 0,
					accelerate : false,

					constructor : function(config) {
						Ext.ux.Spinner.superclass.constructor
								.call(this, config);
						Ext.apply(this, config);
						this.mimicing = false;
					},

					init : function(field) {
						this.field = field;

						this.field.value = new Date(this.field.time)
								.format((this.field.twentyFour) ? this.format
										: this.format);

						field.afterMethod('onRender', this.doRender, this);
						field.afterMethod('onEnable', this.doEnable, this);
						field.afterMethod('onDisable', this.doDisable, this);
						field.afterMethod('afterRender', this.doAfterRender,
								this);
						field.afterMethod('onResize', this.doResize, this);
						field.afterMethod('onFocus', this.doFocus, this);
						field.beforeMethod('onDestroy', this.doDestroy, this);
					},

					doRender : function(ct, position) {
						var el = this.el = this.field.getEl();
						var f = this.field;

						if (!f.wrap) {
							f.wrap = this.wrap = el.wrap({
								cls : "x-form-field-wrap"
							});
						} else {
							this.wrap = f.wrap.addClass('x-form-field-wrap');
						}

						this.trigger = this.wrap.createChild({
							tag : "img",
							src : Ext.BLANK_IMAGE_URL,
							cls : "x-form-trigger " + this.triggerClass
						});

						if (!f.width) {
							this.wrap.setWidth(el.getWidth()
									+ this.trigger.getWidth());
						}

						this.splitter = this.wrap.createChild({
							tag : 'div',
							cls : this.splitterClass,
							style : 'width:13px; height:2px;'
						});
						this.splitter.setRight((Ext.isIE) ? 1 : 2).setTop(10)
								.show();

						this.proxy = this.trigger.createProxy('',
								this.splitter, true);
						this.proxy.addClass("x-form-spinner-proxy");
						this.proxy.setStyle('left', '0px');
						this.proxy.setSize(14, 1);
						this.proxy.hide();
						this.dd = new Ext.dd.DDProxy(this.splitter.dom.id,
								"SpinnerDrag", {
									dragElId : this.proxy.id
								});

						this.initTrigger();
						this.initSpinner();
					},

					doAfterRender : function() {
						var y;
						if (Ext.isIE
								&& this.el.getY() != (y = this.trigger.getY())) {
							this.el.position();
							this.el.setY(y);
						}
					},

					doEnable : function() {
						if (this.wrap) {
							this.wrap.removeClass(this.field.disabledClass);
						}
					},

					doDisable : function() {
						if (this.wrap) {
							this.wrap.addClass(this.field.disabledClass);
							this.el.removeClass(this.field.disabledClass);
						}
					},

					doResize : function(w, h) {
						if (typeof w == 'number') {
							this.el.setWidth(w - this.trigger.getWidth());
						}
						this.wrap.setWidth(this.el.getWidth()
								+ this.trigger.getWidth());
					},

					doFocus : function() {
						if (!this.mimicing) {
							this.wrap.addClass('x-trigger-wrap-focus');
							this.mimicing = true;
							Ext.get(Ext.isIE ? document.body : document).on(
									"mousedown", this.mimicBlur, this, {
										delay : 10
									});
							// this.el.on('keydown', this.checkTab, this);
							this.el.on('keyup', this.checkTab, this);
						}
					},

					// private
					checkTab : function(e) {
						var newtime = getServerTime();
						var v = this.field.getRawValue();
						if (v != "") {
							var sH = si = ss = -1;
							var gH = gi = gs = 0;
							var iH = this.format.indexOf("H");
							var ii = this.format.indexOf("i");
							var is = this.format.indexOf("s");
							var str = "^" + this.format + "$";
							str = str.replace("H", "(\\d{2})");
							str = str.replace("i", "(\\d{2})");
							str = str.replace("s", "(\\d{2})");
							gH = gH + ((iH >= 0) ? 1 : 0)
									+ ((iH > ii && ii >= 0) ? 1 : 0)
									+ ((iH > is && is >= 0) ? 1 : 0);
							gi = gi + ((ii >= 0) ? 1 : 0)
									+ ((ii > iH && iH >= 0) ? 1 : 0)
									+ ((ii > is && is >= 0) ? 1 : 0);
							gs = gs + ((is >= 0) ? 1 : 0)
									+ ((is > iH && iH >= 0) ? 1 : 0)
									+ ((is > ii && ii >= 0) ? 1 : 0);
							var reg = new RegExp(str);
							var g = v.match(reg);
							if (g == null) {
								return false;
							}
							if (gH > 0) {
								newtime.setHours(g[gH]);
							}
							if (gi > 0) {
								newtime.setMinutes(g[gi]);
							}
							if (gs > 0) {
								newtime.setSeconds(g[gs]);
							}
							var t = newtime.getTime();
							var pos = this.getCaretPos(this.field.id);
							/*
							 * if (pos >= 0 && pos <= 2) { var addTime =
							 * 1000*60*60; } else if (pos >= 3 && pos <= 5) {
							 * var addTime = 1000*60; } else if (pos >= 6 && pos <=
							 * 8) { var addTime = 1000; } else if (pos >= 9 &&
							 * pos <= 11) { var addTime = 1000*60*60*12; }
							 * if(v.substr(3,2)>60 || v.substr(6,2)>60){ //t = t +
							 * addTime }
							 */
							this.field.time = t;
							var display = new Date(this.field.time)
									.format((this.field.twentyFour) ? this.format
											: this.format);
							this.field.setRawValue(display);
							this.setCaretTo(this.field.id, pos);
						}
					},

					// private
					mimicBlur : function(e) {
						if (!this.wrap.contains(e.target)
								&& this.field.validateBlur(e)) {
							this.triggerBlur();
						}
					},

					// private
					triggerBlur : function() {
						this.mimicing = false;
						Ext.get(Ext.isIE ? document.body : document).un(
								"mousedown", this.mimicBlur, this);
						this.el.un("keydown", this.checkTab, this);
						this.field.beforeBlur();
						this.wrap.removeClass('x-trigger-wrap-focus');
						this.field.onBlur.call(this.field);
					},

					initTrigger : function() {
						this.trigger.addClassOnOver('x-form-trigger-over');
						this.trigger.addClassOnClick('x-form-trigger-click');
					},

					initSpinner : function() {
						this.field.addEvents({
							'spin' : true,
							'spinup' : true,
							'spindown' : true
						});

						this.keyNav = new Ext.KeyNav(this.el, {
							"up" : function(e) {
								e.preventDefault();
								this.onSpinUp();
							},

							"down" : function(e) {
								e.preventDefault();
								this.onSpinDown();
							},

							"pageUp" : function(e) {
								e.preventDefault();
								this.onSpinUpAlternate();
							},

							"pageDown" : function(e) {
								e.preventDefault();
								this.onSpinDownAlternate();
							},

							scope : this
						});

						this.repeater = new Ext.util.ClickRepeater(
								this.trigger, {
									accelerate : this.accelerate
								});
						this.field.mon(this.repeater, "click",
								this.onTriggerClick, this, {
									preventDefault : true
								});

						this.field.mon(this.trigger, {
							mouseover : this.onMouseOver,
							mouseout : this.onMouseOut,
							mousemove : this.onMouseMove,
							mousedown : this.onMouseDown,
							mouseup : this.onMouseUp,
							scope : this,
							preventDefault : true
						});

						this.field.mon(this.wrap, "mousewheel",
								this.handleMouseWheel, this);

						this.dd.setXConstraint(0, 0, 10)
						this.dd.setYConstraint(1500, 1500, 10);
						this.dd.endDrag = this.endDrag.createDelegate(this);
						this.dd.startDrag = this.startDrag.createDelegate(this);
						this.dd.onDrag = this.onDrag.createDelegate(this);
					},

					onMouseOver : function() {
						if (this.disabled) {
							return;
						}
						var middle = this.getMiddle();
						this.tmpHoverClass = (Ext.EventObject.getPageY() < middle) ? 'x-form-spinner-overup'
								: 'x-form-spinner-overdown';
						this.trigger.addClass(this.tmpHoverClass);
					},

					// private
					onMouseOut : function() {
						this.trigger.removeClass(this.tmpHoverClass);
					},

					// private
					onMouseMove : function() {
						if (this.disabled) {
							return;
						}
						var middle = this.getMiddle();
						if (((Ext.EventObject.getPageY() > middle) && this.tmpHoverClass == "x-form-spinner-overup")
								|| ((Ext.EventObject.getPageY() < middle) && this.tmpHoverClass == "x-form-spinner-overdown")) {
						}
					},

					// private
					onMouseDown : function() {
						if (this.disabled) {
							return;
						}
						var middle = this.getMiddle();
						this.tmpClickClass = (Ext.EventObject.getPageY() < middle) ? 'x-form-spinner-clickup'
								: 'x-form-spinner-clickdown';
						this.trigger.addClass(this.tmpClickClass);
					},

					// private
					onMouseUp : function() {
						this.trigger.removeClass(this.tmpClickClass);
					},

					// private
					onTriggerClick : function() {
						if (this.disabled || this.el.dom.readOnly) {
							return;
						}
						var middle = this.getMiddle();
						var ud = (Ext.EventObject.getPageY() < middle) ? 'Up'
								: 'Down';
						this['onSpin' + ud]();
					},

					// private
					getMiddle : function() {
						var t = this.trigger.getTop();
						var h = this.trigger.getHeight();
						var middle = t + (h / 2);
						return middle;
					},

					// private
					// checks if control is allowed to spin
					isSpinnable : function() {
						if (this.disabled || this.el.dom.readOnly) {
							Ext.EventObject.preventDefault(); // prevent
																// scrolling
																// when
																// disabled/readonly
							return false;
						}
						return true;
					},

					handleMouseWheel : function(e) {
						// disable scrolling when not focused
						if (this.wrap.hasClass('x-trigger-wrap-focus') == false) {
							return;
						}

						var delta = e.getWheelDelta();
						if (delta > 0) {
							this.onSpinUp();
							e.stopEvent();
						} else if (delta < 0) {
							this.onSpinDown();
							e.stopEvent();
						}
					},

					// private
					startDrag : function() {
						this.proxy.show();
						this._previousY = Ext.fly(this.dd.getDragEl()).getTop();
					},

					// private
					endDrag : function() {
						this.proxy.hide();
					},

					// private
					onDrag : function() {
						if (this.disabled) {
							return;
						}
						var y = Ext.fly(this.dd.getDragEl()).getTop();
						var ud = '';

						if (this._previousY > y) {
							ud = 'Up';
						} // up
						if (this._previousY < y) {
							ud = 'Down';
						} // down
						if (ud != '') {
							this['onSpin' + ud]();
						}

						this._previousY = y;
					},

					// private
					onSpinUp : function() {
						if (this.isSpinnable() == false) {
							return;
						}
						if (Ext.EventObject.shiftKey == true) {
							this.onSpinUpAlternate();
							return;
						} else {
							this.spin(false, false);
						}
						this.field.fireEvent("spin", this);
						this.field.fireEvent("spinup", this);
					},

					// private
					onSpinDown : function() {
						if (this.isSpinnable() == false) {
							return;
						}
						if (Ext.EventObject.shiftKey == true) {
							this.onSpinDownAlternate();
							return;
						} else {
							this.spin(true, false);
						}
						this.field.fireEvent("spin", this);
						this.field.fireEvent("spindown", this);
					},

					// private
					onSpinUpAlternate : function() {
						if (this.isSpinnable() == false) {
							return;
						}
						this.spin(false, true);
						this.field.fireEvent("spin", this);
						this.field.fireEvent("spinup", this);
					},

					// private
					onSpinDownAlternate : function() {
						if (this.isSpinnable() == false) {
							return;
						}
						this.spin(true, true);
						this.field.fireEvent("spin", this);
						this.field.fireEvent("spindown", this);
					},

					// ///////////////////

					checkFormat : function(text) {
						text = String(text);
						(text.length == 1) ? text = "0" + text : text;
						return text;
					},

					setCaretTo : function(id, pos) {
						var obj = document.getElementById(id);
						if (obj.createTextRange) {
							var range = obj.createTextRange();
							range.move("character", pos);
							range.select();
						} else if (obj.selectionStart) {
							obj.focus();
							obj.setSelectionRange(pos, pos);
						}
					},

					getCaretPos : function(id) {
						var el = document.getElementById(id);
						var rng, ii = -1;
						if (typeof el.selectionStart == "number") {
							ii = el.selectionStart;
						} else if (document.selection && el.createTextRange) {
							rng = document.selection.createRange();
							rng.collapse(true);
							rng.moveStart("character", -el.value.length);
							ii = rng.text.length;
						}
						return ii;
					},

					spin : function(down, alternate) {
						var sH = si = ss = -1;
						var gH = gi = gs = 0;
						var iH = this.format.indexOf("H");
						var ii = this.format.indexOf("i");
						var is = this.format.indexOf("s");
						gH = gH + ((iH >= 0) ? 1 : 0)
								+ ((iH > ii && ii >= 0) ? 1 : 0)
								+ ((iH > is && is >= 0) ? 1 : 0);
						gi = gi + ((ii >= 0) ? 1 : 0)
								+ ((ii > iH && iH >= 0) ? 1 : 0)
								+ ((ii > is && is >= 0) ? 1 : 0);
						gs = gs + ((is >= 0) ? 1 : 0)
								+ ((is > iH && iH >= 0) ? 1 : 0)
								+ ((is > ii && ii >= 0) ? 1 : 0);
						if (gH > 0) {
							sH = iH + gH - 1;
						}
						if (gi > 0) {
							si = ii + gi - 1;
						}
						if (gs > 0) {
							ss = is + gs - 1;
						}

						var pos = this.getCaretPos(this.field.id);

						if (this.field.twentyFour) {
							if (sH >= 0 && pos >= sH && pos <= sH + 2) {
								var addTime = 1000 * 60 * 60;
							} else if (si >= 0 && pos >= si && pos <= si + 2) {
								var addTime = 1000 * 60;
							} else if (ss >= 0 && pos >= ss && pos <= ss + 2) {
								var addTime = 1000;
							}
						} else {
							if (sH >= 0 && pos >= sH && pos <= sH + 2) {
								var addTime = 1000 * 60 * 60;
							} else if (si >= 0 && pos >= si && pos <= si + 2) {
								var addTime = 1000 * 60;
							} else if (ss >= 0 && pos >= ss && pos <= ss + 2) {
								var addTime = 1000;
							} else if (pos > ss + 2) {
								var addTime = 1000 * 60 * 60 * 12;
							}
						}

						if (down) {
							var newTime = new Date(this.field.time).getTime()
									- addTime;
						} else {
							var newTime = new Date(this.field.time).getTime()
									+ addTime;
						}
						this.field.time = new Date(newTime).getTime();
						var display = new Date(this.field.time)
								.format((this.field.twentyFour) ? this.format
										: this.format);
						this.field.setRawValue(display);
						this.setCaretTo(this.field.id, pos);
					},

					doDestroy : function() {
						if (this.trigger) {
							this.trigger.remove();
						}
						if (this.wrap) {
							this.wrap.remove();
							delete this.field.wrap;
						}

						if (this.splitter) {
							this.splitter.remove();
						}

						if (this.dd) {
							this.dd.unreg();
							this.dd = null;
						}

						if (this.proxy) {
							this.proxy.remove();
						}

						if (this.repeater) {
							this.repeater.purgeListeners();
						}
					}
				});

// backwards compat
Ext.form.Spinner = Ext.ux.Spinner;

/**
 * @ignore Ext.ux.form.SpinnerField extends Ext.form.NumberField Creates a field
 *         utilizing Ext.ux.Spinner xtype spinnerfield
 * 
 * modified by Mitchell Simoens This modification was to allow the
 * Ext.ux.form.SpinnerField to allow a string. To accomplish, all I had to do
 * was change the extended component. Also change the Extension name to not
 * create confusion.
 */
Ext.ux.form.TimeField = Ext
		.extend(
				Ext.form.TriggerField,
				{
					actionMode : 'wrap',
					deferHeight : true,
					autoSize : Ext.emptyFn,
					onBlur : Ext.emptyFn,
					adjustSize : Ext.BoxComponent.prototype.adjustSize,

					constructor : function(config) {
						// ,
						// 'incrementValue,alternateIncrementValue,accelerate,defaultValue,triggerClass,splitterClass'
						var spinnerConfig = Ext.apply({}, config);

						var spl = this.spinner = new Ext.ux.Spinner(
								spinnerConfig);

						var now = getServerTime();
						if (config.value != undefined) {
							now.setHours(config.value.substr(0, 2));
							now.setMinutes(config.value.substr(3, 2));
							now.setSeconds(config.value.substr(6, 2));
						}

						config.time = now.getTime();

						var plugins = config.plugins ? (Ext
								.isArray(config.plugins) ? config.plugins
								.push(spl) : [ config.plugins, spl ]) : spl;

						Ext.ux.form.TimeField.superclass.constructor.call(this,
								Ext.apply(config, {
									plugins : plugins
								}));
						if (config.value != undefined) {
							this.setValue(config.value);
						}
					},

					isAM : function() {
						var hour = new Date(this.time).getHours();
						return (hour < 12) ? true : false;
					},

					isPM : function() {
						var hour = new Date(this.time).getHours();
						return (hour >= 12) ? true : false;
					},

					getValue : function(format) {
						if (!format) {
							if (this.twentyFour) {
								format = this.format;
							} else {
								format = this.format;
							}
						}
						return new Date(this.time).format(format);
					},

					setValue : function(value, format) {
						if (typeof (value) == 'string') {
							Ext.ux.form.TimeField.superclass.setValue.apply(
									this, arguments);
						} else {
							if (!format) {
								if (this.twentyFour) {
									format = this.format;
								} else {
									format = this.format;
								}
							}
							this.time = value;
							Ext.ux.form.TimeField.superclass.setValue.apply(
									this, [ value.format(format) ]);
						}

					},

					// private
					getResizeEl : function() {
						return this.wrap;
					},

					// private
					getPositionEl : function() {
						return this.wrap;
					},

					// private
					alignErrorIcon : function() {
						if (this.wrap) {
							this.errorIcon
									.alignTo(this.wrap, 'tl-tr', [ 2, 0 ]);
						}
					},

					validateBlur : function() {
						return true;
					},

					validateValue : function(value) {
						var timeInvalidText = "\u65f6\u95f4\u683c\u5f0f\u4e0d\u6b63\u786e";
						Ext.ux.form.TimeField.superclass.validateValue.call(
								this, arguments);
						if (value != "") {
							var sH = si = ss = -1;
							var gH = gi = gs = 0;
							var iH = this.format.indexOf("H");
							var ii = this.format.indexOf("i");
							var is = this.format.indexOf("s");
							var str = "^" + this.format + "$";
							str = str.replace("H", "(\\d{2})");
							str = str.replace("i", "(\\d{2})");
							str = str.replace("s", "(\\d{2})");
							gH = gH + ((iH >= 0) ? 1 : 0)
									+ ((iH > ii && ii >= 0) ? 1 : 0)
									+ ((iH > is && is >= 0) ? 1 : 0);
							gi = gi + ((ii >= 0) ? 1 : 0)
									+ ((ii > iH && iH >= 0) ? 1 : 0)
									+ ((ii > is && is >= 0) ? 1 : 0);
							gs = gs + ((is >= 0) ? 1 : 0)
									+ ((is > iH && iH >= 0) ? 1 : 0)
									+ ((is > ii && ii >= 0) ? 1 : 0);
							var reg = new RegExp(str);
							var g = value.match(reg);
							if (g == null) {
								this.markInvalid(timeInvalidText);
								return false;
							}
							if ((gH > 0 && g[gH] > 24)
									|| (gi > 0 && g[gi] > 60)
									|| (gs > 0 && g[gs] > 60)) {
								this.markInvalid(timeInvalidText);
								return false;
							}
						}
						return true;
					}
				});

Ext.reg('timefield', Ext.ux.form.TimeField);

// backwards compat
Ext.form.TimeField = Ext.ux.form.TimeField;

/**
 * @ignore Ext.form.DateField Ext.form.TriggerField Provides a date input field
 *         with a {link Ext.DatePicker} dropdown and automatic date validation.
 * 
 * Create a new DateField {Object} config
 */
Ext.form.DateField = Ext
		.extend(
				Ext.form.TriggerField,
				{
					/**
					 * cfg {String} format The default date format string which
					 * can be overriden for localization support. The format
					 * must be valid according to {link Date#parseDate}
					 * (defaults to 'm/d/Y').
					 */
					format : "Y-m",
					/**
					 * cfg {String} altFormats Multiple date formats separated
					 * by "|" to try when parsing a user input value and it
					 * doesn't match the defined format (defaults to
					 * 'm/d/Y|n/j/Y|n/j/y|m/j/y|n/d/y|m/j/Y|n/d/Y|m-d-y|m-d-Y|m/d|m-d|md|mdy|mdY|d|Y-m-d').
					 */
					altFormats : "m/d/Y|n/j/Y|n/j/y|m/j/y|n/d/y|m/j/Y|n/d/Y|m-d-y|m-d-Y|m/d|m-d|md|mdy|mdY|d|Y-m-d",
					/**
					 * cfg {String} disabledDaysText The tooltip to display when
					 * the date falls on a disabled day (defaults to 'Disabled')
					 */
					disabledDaysText : "Disabled",
					/**
					 * cfg {String} disabledDatesText The tooltip text to
					 * display when the date falls on a disabled date (defaults
					 * to 'Disabled')
					 */
					disabledDatesText : "Disabled",
					/**
					 * cfg {String} minText The error text to display when the
					 * date in the cell is before minValue (defaults to 'The
					 * date in this field must be after {minValue}').
					 */
					minText : "The date in this field must be equal to or after {0}",
					/**
					 * cfg {String} maxText The error text to display when the
					 * date in the cell is after maxValue (defaults to 'The date
					 * in this field must be before {maxValue}').
					 */
					maxText : "The date in this field must be equal to or before {0}",
					/**
					 * cfg {String} The error text to display when the date in
					 * the field is invalid (defaults to '{value} is not a valid
					 * date - it must be in the format {format}').
					 */
					invalidText : "{0} is not a valid date - it must be in the format {1}",
					/**
					 * cfg {String} triggerClass An additional CSS class used to
					 * style the trigger button. The trigger will always get the
					 * class 'x-form-trigger' and triggerClass will be
					 * <b>appended</b> if specified (defaults to
					 * 'x-form-date-trigger' which displays a calendar icon).
					 */
					triggerClass : 'x-form-date-trigger',
					/**
					 * cfg {Boolean} showToday False to hide the footer area of
					 * the DatePicker containing the Today button and disable
					 * the keyboard handler for spacebar that selects the
					 * current date (defaults to true).
					 */
					showToday : true,
					/**
					 * cfg {Date/String} minValue The minimum allowed date. Can
					 * be either a Javascript date object or a string date in a
					 * valid format (defaults to null).
					 */
					/**
					 * cfg {Date/String} maxValue The maximum allowed date. Can
					 * be either a Javascript date object or a string date in a
					 * valid format (defaults to null).
					 */
					/**
					 * cfg {Array} disabledDays An array of days to disable, 0
					 * based. For example, [0, 6] disables Sunday and Saturday
					 * (defaults to null).
					 */
					/**
					 * cfg {Array} disabledDates An array of "dates" to disable,
					 * as strings. These strings will be used to build a dynamic
					 * regular expression so they are very powerful. Some
					 * examples:
					 * <ul>
					 * <li>["03/08/2003", "09/16/2003"] would disable those
					 * exact dates</li>
					 * <li>["03/08", "09/16"] would disable those days for
					 * every year</li>
					 * <li>["^03/08"] would only match the beginning (useful if
					 * you are using short years)</li>
					 * <li>["03/../2006"] would disable every day in March 2006</li>
					 * <li>["^03"] would disable every day in every March</li>
					 * </ul>
					 * Note that the format of the dates included in the array
					 * should exactly match the {link #format} config. In order
					 * to support regular expressions, if you are using a date
					 * format that has "." in it, you will have to escape the
					 * dot when restricting dates. For example:
					 * ["03\\.08\\.03"].
					 */
					/**
					 * cfg {String/Object} autoCreate A DomHelper element spec,
					 * or true for a default element spec (defaults to {tag:
					 * "input", type: "text", size: "10", autocomplete: "off"})
					 */

					// private
					defaultAutoCreate : {
						tag : "input",
						type : "text",
						size : "10",
						autocomplete : "off"
					},

					initComponent : function() {
						Ext.form.DateField.superclass.initComponent.call(this);
						this.addEvents('select');

						if (typeof this.minValue == "string") {
							this.minValue = this.parseDate(this.minValue);
						}
						if (typeof this.maxValue == "string") {
							this.maxValue = this.parseDate(this.maxValue);
						}
						this.ddMatch = null;
						this.initDisabledDays();
					},

					// private
					initDisabledDays : function() {
						if (this.disabledDates) {
							var dd = this.disabledDates;
							var re = "(?:";
							for (var i = 0; i < dd.length; i++) {
								re += dd[i];
								if (i != dd.length - 1)
									re += "|";
							}
							this.disabledDatesRE = new RegExp(re + ")");
						}
					},

					/**
					 * Replaces any existing disabled dates with new values and
					 * refreshes the DatePicker. param {Array} disabledDates An
					 * array of date strings (see the {link #disabledDates}
					 * config for details on supported values) used to disable a
					 * pattern of dates.
					 */
					setDisabledDates : function(dd) {
						this.disabledDates = dd;
						this.initDisabledDays();
						if (this.menu) {
							this.menu.picker
									.setDisabledDates(this.disabledDatesRE);
						}
					},

					/**
					 * Replaces any existing disabled days (by index, 0-6) with
					 * new values and refreshes the DatePicker. param {Array}
					 * disabledDays An array of disabled day indexes. See the
					 * {link #disabledDays} config for details on supported
					 * values.
					 */
					setDisabledDays : function(dd) {
						this.disabledDays = dd;
						if (this.menu) {
							this.menu.picker.setDisabledDays(dd);
						}
					},

					/**
					 * Replaces any existing {link #minValue} with the new value
					 * and refreshes the DatePicker. param {Date} value The
					 * minimum date that can be selected
					 */
					setMinValue : function(dt) {
						this.minValue = (typeof dt == "string" ? this
								.parseDate(dt) : dt);
						if (this.menu) {
							this.menu.picker.setMinDate(this.minValue);
						}
					},

					/**
					 * Replaces any existing {link #maxValue} with the new value
					 * and refreshes the DatePicker. param {Date} value The
					 * maximum date that can be selected
					 */
					setMaxValue : function(dt) {
						this.maxValue = (typeof dt == "string" ? this
								.parseDate(dt) : dt);
						if (this.menu) {
							this.menu.picker.setMaxDate(this.maxValue);
						}
					},

					// private
					validateValue : function(value) {
						value = this.formatDate(value);
						if (!Ext.form.DateField.superclass.validateValue.call(
								this, value)) {
							return false;
						}
						if (value.length < 1) { // if it's blank and textfield
												// didn't flag it then it's
												// valid
							return true;
						}
						var svalue = value;
						value = this.parseDate(value);
						if (!value) {
							this.invalidText = "{0} \u662f\u65e0\u6548\u7684\u65e5\u671f - \u5fc5\u987b\u7b26\u5408\u683c\u5f0f\uff1a {1}";
							this.markInvalid(String.format(this.invalidText,
									svalue, this.format));
							return false;
						}
						var time = value.getTime();
						if (this.minValue && time < this.minValue.getTime()) {
							this.markInvalid(String.format(this.minText, this
									.formatDate(this.minValue)));
							return false;
						}
						if (this.maxValue && time > this.maxValue.getTime()) {
							this.markInvalid(String.format(this.maxText, this
									.formatDate(this.maxValue)));
							return false;
						}
						if (this.disabledDays) {
							var day = value.getDay();
							for (var i = 0; i < this.disabledDays.length; i++) {
								if (day === this.disabledDays[i]) {
									this.markInvalid(this.disabledDaysText);
									return false;
								}
							}
						}
						var fvalue = this.formatDate(value);
						if (this.ddMatch && this.ddMatch.test(fvalue)) {
							this.markInvalid(String.format(
									this.disabledDatesText, fvalue));
							return false;
						}
						return true;
					},

					// private
					// Provides logic to override the default
					// TriggerField.validateBlur which just returns true
					validateBlur : function() {
						return !this.menu || !this.menu.isVisible();
					},

					/**
					 * Returns the current date value of the date field. return
					 * {Date} The date value
					 */
					getValue : function() {
						return this
								.parseDate(Ext.form.DateField.superclass.getValue
										.call(this))
								|| "";
					},

					/**
					 * Sets the value of the date field. You can pass a date
					 * object or any string that can be parsed into a valid
					 * date, using DateField.format as the date format,
					 * according to the same rules as {link Date#parseDate} (the
					 * default format used is "m/d/Y"). <br />
					 * Usage:
					 * 
					 * <pre><code>
					 * //All of these calls set the same date value (May 4, 2006)
					 * 
					 * //Pass a date object:
					 * var dt = new Date('5/4/2006');
					 * dateField.setValue(dt);
					 * 
					 * //Pass a date string (default format):
					 * dateField.setValue('05/04/2006');
					 * 
					 * //Pass a date string (custom format):
					 * dateField.format = 'Y-m-d';
					 * dateField.setValue('2006-05-04');
					 * </code></pre>
					 * 
					 * param {String/Date} date The date or valid date string
					 */
					setValue : function(date) {
						Ext.form.DateField.superclass.setValue.call(this, this
								.formatDate(this.parseDate(date)));
					},

					// private
					parseDate : function(value) {
						if (!value || Ext.isDate(value)) {
							return value;
						}
						var v = Date.parseDate(value, this.format);
						if (!v && this.altFormats) {
							if (!this.altFormatsArray) {
								this.altFormatsArray = this.altFormats
										.split("|");
							}
							for (var i = 0, len = this.altFormatsArray.length; i < len
									&& !v; i++) {
								v = Date.parseDate(value,
										this.altFormatsArray[i]);
							}
						}
						return v;
					},

					// private
					onDestroy : function() {
						if (this.menu) {
							this.menu.destroy();
						}
						if (this.wrap) {
							this.wrap.remove();
						}
						Ext.form.DateField.superclass.onDestroy.call(this);
					},

					// private
					formatDate : function(date) {
						return Ext.isDate(date) ? date.dateFormat(this.format)
								: date;
					},

					// private
					menuListeners : {
						select : function(m, d) {
							this.setValue(d);
							this.fireEvent('select', this, d);
						},
						show : function() { // retain focus styling
							this.onFocus();
						},
						hide : function() {
							this.focus.defer(10, this);
							var ml = this.menuListeners;
							this.menu.un("select", ml.select, this);
							this.menu.un("show", ml.show, this);
							this.menu.un("hide", ml.hide, this);
						}
					},

					/**
					 * method onTriggerClick hide
					 */
					// private
					// Implements the default empty TriggerField.onTriggerClick
					// function to display the DatePicker
					onTriggerClick : function() {
						if (this.disabled) {
							return;
						}
						if (this.menu == null) {
							this.menu = new Ext.menu.DateMenu();
						}
						Ext.apply(this.menu.picker, {
							minDate : this.minValue,
							maxDate : this.maxValue,
							disabledDatesRE : this.ddMatch,
							disabledDatesText : this.disabledDatesText,
							disabledDays : this.disabledDays,
							disabledDaysText : this.disabledDaysText,
							format : this.format,
							showToday : this.showToday,
							minText : String.format(this.minText, this
									.formatDate(this.minValue)),
							maxText : String.format(this.maxText, this
									.formatDate(this.maxValue)),
							menu : this.menu,
							input : this
						// davi
						});
						this.menu.on(Ext.apply({}, this.menuListeners, {
							scope : this
						}));
						this.menu.picker.setValue(this.getValue()
								|| getServerTime());
						this.menu.show(this.el, "tl-bl?");
						// --xuke
						if (this.format.indexOf('d') == -1) {
							this.menu.picker.showMonthPicker();
						}
					},

					// private
					beforeBlur : function() {
						var v = this.parseDate(this.getRawValue());
						if (v) {
							this.setValue(v);
						}
					}

				/**
				 * cfg {Boolean} grow hide
				 */
				/**
				 * cfg {Number} growMin hide
				 */
				/**
				 * cfg {Number} growMax hide
				 */
				/**
				 * hide method autoSize
				 */
				});
Ext.reg('monthfield', Ext.form.DateField);
Wonders.form.MonthField = Ext.form.DateField;

/**
 * @ignore
 * @class Ext.form.CheckboxGroup
 * @extends Ext.form.Field A grouping container for {@link Ext.form.Checkbox}
 *          controls.
 * @constructor Creates a new CheckboxGroup
 * @param {Object}
 *            config Configuration options
 */
Ext.form.CheckboxGroup = Ext
		.extend(
				Ext.form.Field,
				{
					/**
					 * @cfg {String/Number/Array} columns Specifies the number
					 *      of columns to use when displaying grouped
					 *      checkbox/radio controls using automatic layout. This
					 *      config can take several types of values:
					 *      <ul>
					 *      <li><b>'auto'</b> :
					 *      <p class="sub-desc">
					 *      The controls will be rendered one per column on one
					 *      row and the width of each column will be evenly
					 *      distributed based on the width of the overall field
					 *      container. This is the default.
					 *      </p>
					 *      </li>
					 *      <li><b>Number</b> :
					 *      <p class="sub-desc">
					 *      If you specific a number (e.g., 3) that number of
					 *      columns will be created and the contained controls
					 *      will be automatically distributed based on the value
					 *      of {@link #vertical}.
					 *      </p>
					 *      </li>
					 *      <li><b>Array</b> : Object
					 *      <p class="sub-desc">
					 *      You can also specify an array of column widths,
					 *      mixing integer (fixed width) and float (percentage
					 *      width) values as needed (e.g., [100, .25, .75]). Any
					 *      integer values will be rendered first, then any
					 *      float values will be calculated as a percentage of
					 *      the remaining space. Float values do not have to add
					 *      up to 1 (100%) although if you want the controls to
					 *      take up the entire field container you should do so.
					 *      </p>
					 *      </li>
					 *      </ul>
					 */
					columns : 'auto',
					/**
					 * @cfg {Boolean} vertical True to distribute contained
					 *      controls across columns, completely filling each
					 *      column top to bottom before starting on the next
					 *      column. The number of controls in each column will
					 *      be automatically calculated to keep columns as even
					 *      as possible. The default value is false, so that
					 *      controls will be added to columns one at a time,
					 *      completely filling each row left to right before
					 *      starting on the next row.
					 */
					vertical : false,
					/**
					 * @cfg {Boolean} allowBlank False to validate that at least
					 *      one item in the group is checked (defaults to true).
					 *      If no items are selected at validation time,
					 *      {@link @blankText} will be used as the error text.
					 */
					allowBlank : true,
					/**
					 * @cfg {String} blankText Error text to display if the
					 *      {@link #allowBlank} validation fails (defaults to
					 *      "You must select at least one item in this group")
					 */
					blankText : "You must select at least one item in this group",

					// private
					defaultType : 'checkbox',

					// private
					groupCls : 'x-form-check-group',

					// private
					valueField : 'value',

					// private
					displayField : 'text',

					// private
					dataFields : [],

					// private
					data : [],

					childItems : [],

					enableTooltip : false,

					initComponent : function() {
						Ext.form.CheckboxGroup.superclass.initComponent
								.call(this);
						// 动态加载（url或者data+dataFields），其items属性不存在，添加判断
						if (this.items) {

						} else {
							this.items = [];
						}

						if (!this.store) {
							this.store = new Ext.data.SimpleStore({
								fields : this.dataFields,
								data : this.data
							});
							this.initGroup();
						} else {
							this.bindStore();
						}
					},

					// private
					onRender : function(ct, position) {
						if (!this.el) {
							var panelCfg = {
								width : this.width,
								cls : this.groupCls,
								border : false,
								renderTo : ct
							};

							this.panel = new Ext.Panel(panelCfg);
							this.el = this.panel.getEl();

							var tpl = new Ext.XTemplate(
									'<table><tr><tpl for=\".\"><td><div id=\"{id}_div\"></div></td></tpl></tr></table>');
							tpl.overwrite(this.panel.body, this.items);

							this.childItems = new Ext.util.MixedCollection();
							for (var i = 0; i < this.items.length; i++) {
								var checkbox = new Ext.form.Checkbox(
										this.items[i]);
								// tooltip
								if (this.enableTooltip) {
									if (this.items[i].tooltip) {
										if (typeof this.items[i].tooltip == 'object') {
											Ext.QuickTips.register(Ext.apply({
												target : checkbox.id
											}, this.items[i].tooltip));
										} else {
											checkbox.el.dom[this.items[i].tooltipType] = this.items[i].tooltip;
											if (checkbox.el.dom.nextSibling)
												checkbox.el.dom.nextSibling[this.items[i].tooltipType] = this.items[i].tooltip;
										}
									}
								}
								this.childItems.add(checkbox);
							}
						}
						this.hiddenName = this.name;
						Ext.form.CheckboxGroup.superclass.onRender.call(this,
								ct, position);
						// 根据value属性设置选中状态
						this.setValue(this.value);
					},

					initGroup : function() {

						for (var len = this.items.length, i = len - 1; i >= 0; i--) {
							if (this.items[i].mode == 'data') {
								this.items.removeAt(i);
							}
						}
						for (var i = 0, len = this.store.getCount(); i < len; i++) {
							var record = this.store.getAt(i);
							if (record.data.id == undefined
									|| record.data.id == '') {
								record.data.id = this.id + '_' + i;
							}
							record.data.mode = 'data';
							record.data.boxLabel = record.data[this.displayField];
							record.data.inputValue = record.data[this.valueField];
							record.data.renderTo = record.data.id + '_div';
							if (record.data.width == 0) {
								record.data.autoWidth = true;
							}
							record.data.tooltipType = 'qtip';
							record.data.name = this.name;
							this.items[this.items.length] = record.data;
						}
					},

					bindStore : function() {
						this.store.on('beforeload', this.onBeforeLoad, this);
						this.store.on('load', this.onLoad, this);
					},

					// private
					validateValue : function(value) {
						if (!this.allowBlank) {
							var blank = true;
							this.childItems.each(function(f) {
								if (f.el.dom.checked) {
									return blank = false;
								}
							}, this);
							if (blank) {
								this.markInvalid(this.blankText);
								return false;
							}
						}
						return true;
					},

					onBeforeLoad : Ext.emptyFn,

					onLoad : function() {
						this.initGroup();
						var parentNode = this.el.dom.parentNode;
						this.rendered = false;
						this.el.remove();
						this.el = null;
						this.render(parentNode);
						this.setValue(this.value);
					},

					// private
					onDisable : function() {
						this.childItems.each(function(item) {
							item.disable();
						})
					},

					// private
					onEnable : function() {
						this.childItems.each(function(item) {
							item.enable();
						})
					},

					// private
					onResize : function(w, h) {
						this.panel.setSize(w, h);
						this.panel.doLayout();
					},

					// inherit docs from Field
					reset : function() {
						Ext.form.CheckboxGroup.superclass.reset.call(this);
						this.childItems.each(function(c) {
							if (c.reset) {
								c.reset();
							}
						}, this);
					},

					/**
					 * @cfg {String} name
					 * @hide
					 */
					/**
					 * @method initValue
					 * @hide
					 */
					initValue : Ext.emptyFn,
					/**
					 * @method getValue
					 * @hide
					 */
					getValue : function() {
						var v = "";
						this.childItems.each(function(item) {
							if (item.el.dom.checked) {
								v = v + item.el.dom.value + ",";
							}
						});
						if (v.lastIndexOf(",") == v.length) {
							v = v.substring(0, v.length - 1);
						}
						return v;
					},
					/**
					 * @method getRawValue
					 * @hide
					 */
					getRawValue : Ext.emptyFn,
					/**
					 * @method setValue
					 * @hide
					 */
					setValue : function(v) {
						if (v) {
							v = v + "";
							var values = v.split(",");
							this.childItems
									.each(function(item) {
										for (var j = 0, len2 = values.length; j < len2; j++) {
											if (item.el.dom.value == values[j]
													.trim()) {
												item.el.dom.checked = true;
												break;
											}
										}
									});
						}
						Ext.form.CheckboxGroup.superclass.setValue
								.call(this, v);
						this.value = v;
					},
					/**
					 * @method setRawValue
					 * @hide
					 */
					setRawValue : Ext.emptyFn

				});

Ext.reg('checkboxgroup', Ext.form.CheckboxGroup);

/**
 * @ignore
 * @class Ext.form.RadioGroup
 * @extends Ext.form.CheckboxGroup A grouping container for
 *          {@link Ext.form.Radio} controls.
 * @constructor Creates a new CheckboxGroup
 * @param {Object}
 *            config Configuration options
 */
Ext.form.RadioGroup = Ext
		.extend(
				Ext.form.CheckboxGroup,
				{
					/**
					 * @cfg {Boolean} allowBlank True to allow every item in the
					 *      group to be blank (defaults to false). If allowBlank =
					 *      false and no items are selected at validation time,
					 *      {@link @blankText} will be used as the error text.
					 */
					allowBlank : true,
					/**
					 * @cfg {String} blankText Error text to display if the
					 *      {@link #allowBlank} validation fails (defaults to
					 *      "You must select one item in this group")
					 */
					blankText : "You must select one item in this group",

					// private
					defaultType : 'radio',

					// private
					groupCls : 'x-form-radio-group',

					// private
					onRender : function(ct, position) {
						if (!this.el) {
							var panelCfg = {
								width : this.width,
								cls : this.groupCls,
								border : false,
								renderTo : ct
							};

							this.panel = new Ext.Panel(panelCfg);
							this.el = this.panel.getEl();

							var tpl = new Ext.XTemplate(
									'<table><tr><tpl for=\".\"><td><div id=\"{id}_div\"></div></td></tpl></tr></table>');
							tpl.overwrite(this.panel.body, this.items);

							this.childItems = new Ext.util.MixedCollection();
							for (var i = 0; i < this.items.length; i++) {
								var radio = new Ext.form.Radio(this.items[i]);
								// tooltip
								if (this.enableTooltip) {
									if (this.items[i].tooltip) {
										if (typeof this.items[i].tooltip == 'object') {
											Ext.QuickTips.register(Ext.apply({
												target : radio.id
											}, this.items[i].tooltip));
										} else {
											radio.el.dom[this.items[i].tooltipType] = this.items[i].tooltip;
											if (radio.el.dom.nextSibling)
												radio.el.dom.nextSibling[this.items[i].tooltipType] = this.items[i].tooltip;
										}
									}
								}
								this.childItems.add(radio);
							}
						}
						this.hiddenName = this.name;
						Ext.form.RadioGroup.superclass.onRender.call(this, ct,
								position);
						// 根据value属性设置选中状态
						this.setValue(this.value);
					},

					/**
					 * @method getValue
					 * @hide
					 */
					getValue : function() {
						this.childItems.each(function(item) {
							if (item.el.dom.checked) {
								return item.el.dom.value;
							}
						});
						return "";
					},

					/**
					 * @method setValue
					 * @hide
					 */
					setValue : function(v) {
						this.childItems.each(function(item) {
							if (item.el.dom.value == v) {
								item.el.dom.checked = true;
							}
						});
						Ext.form.RadioGroup.superclass.setValue.call(this, v);
						this.value = v;
					}
				});

Ext.reg('radiogroup', Ext.form.RadioGroup);

/**
 * @ignore Ext.ux.DDView
 *         <p>
 *         A DnD-enabled version of {link Ext.DataView}. Drag/drop is
 *         implemented by adding {link Ext.data.Record}s to the target DDView.
 *         If copying is not being performed, the original {link
 *         Ext.data.Record} is removed from the source DDView.
 *         </p>
 *         constructor Create a new DDView param {Object} config The
 *         configuration properties.
 */
Ext.ux.DDView = function(config) {
	if (!config.itemSelector) {
		var tpl = config.tpl;
		if (this.classRe.test(tpl)) {
			config.tpl = tpl.replace(this.classRe,
					'class=$1x-combo-list-item $2$1');
		} else {
			config.tpl = tpl.replace(this.tagRe,
					'$1 class="x-combo-list-item" $2');
		}
		config.itemSelector = ".x-combo-list-item";
	}
	Ext.ux.DDView.superclass.constructor.call(this, Ext.apply(config, {
		border : false
	}));
};

Ext
		.extend(
				Ext.ux.DDView,
				Ext.DataView,
				{
					/**
					 * cfg {String/Array} dragGroup The ddgroup name(s) for the
					 * View's DragZone (defaults to undefined).
					 */
					/**
					 * cfg {String/Array} dropGroup The ddgroup name(s) for the
					 * View's DropZone (defaults to undefined).
					 */
					/**
					 * cfg {Boolean} copy Causes drag operations to copy nodes
					 * rather than move (defaults to false).
					 */
					/**
					 * cfg {Boolean} allowCopy Causes ctrl/drag operations to
					 * copy nodes rather than move (defaults to false).
					 */
					/**
					 * cfg {String} sortDir Sort direction for the view, 'ASC'
					 * or 'DESC' (defaults to 'ASC').
					 */
					sortDir : 'ASC',

					// private
					isFormField : true,
					classRe : /class=(['"])(.*)\1/,
					tagRe : /(<\w*)(.*?>)/,
					reset : Ext.emptyFn,
					clearInvalid : Ext.form.Field.prototype.clearInvalid,

					// private
					afterRender : function() {
						Ext.ux.DDView.superclass.afterRender.call(this);
						if (this.dragGroup) {
							this.setDraggable(this.dragGroup.split(","));
						}
						if (this.dropGroup) {
							this.setDroppable(this.dropGroup.split(","));
						}
						if (this.deletable) {
							this.setDeletable();
						}
						this.isDirtyFlag = false;
						this.addEvents("drop");
					},

					// private
					validate : function() {
						return true;
					},

					// private
					destroy : function() {
						this.purgeListeners();
						this.getEl().removeAllListeners();
						this.getEl().remove();
						if (this.dragZone) {
							if (this.dragZone.destroy) {
								this.dragZone.destroy();
							}
						}
						if (this.dropZone) {
							if (this.dropZone.destroy) {
								this.dropZone.destroy();
							}
						}
					},

					/**
					 * Allows this class to be an Ext.form.Field so it can be
					 * found using {link Ext.form.BasicForm#findField}.
					 */
					getName : function() {
						return this.name;
					},

					/**
					 * Loads the View from a JSON string representing the
					 * Records to put into the Store. param {String} value The
					 * JSON string
					 */
					setValue : function(v) {
						if (!this.store) {
							throw "DDView.setValue(). DDView must be constructed with a valid Store";
						}
						var data = {};
						data[this.store.reader.meta.root] = v ? [].concat(v)
								: [];
						this.store.proxy = new Ext.data.MemoryProxy(data);
						this.store.load();
					},

					/**
					 * Returns the view's data value as a list of ids. return
					 * {String} A parenthesised list of the ids of the Records
					 * in the View, e.g. (1,3,8).
					 */
					getValue : function() {
						var result = '(';
						this.store.each(function(rec) {
							result += rec.id + ',';
						});
						return result.substr(0, result.length - 1) + ')';
					},

					getIds : function() {
						var i = 0, result = new Array(this.store.getCount());
						this.store.each(function(rec) {
							result[i++] = rec.id;
						});
						return result;
					},

					/**
					 * Returns true if the view's data has changed, else false.
					 * return {Boolean}
					 */
					isDirty : function() {
						return this.isDirtyFlag;
					},

					/**
					 * Part of the Ext.dd.DropZone interface. If no target node
					 * is found, the whole Element becomes the target, and this
					 * causes the drop gesture to append.
					 */
					getTargetFromEvent : function(e) {
						var target = e.getTarget();
						while ((target !== null)
								&& (target.parentNode != this.el.dom)) {
							target = target.parentNode;
						}
						if (!target) {
							target = this.el.dom.lastChild || this.el.dom;
						}
						return target;
					},

					/**
					 * Create the drag data which consists of an object which
					 * has the property "ddel" as the drag proxy element.
					 */
					getDragData : function(e) {
						var target = this.findItemFromChild(e.getTarget());
						if (target) {
							if (!this.isSelected(target)) {
								delete this.ignoreNextClick;
								this.onItemClick(target, this.indexOf(target),
										e);
								this.ignoreNextClick = true;
							}
							var dragData = {
								sourceView : this,
								viewNodes : [],
								records : [],
								copy : this.copy
										|| (this.allowCopy && e.ctrlKey)
							};
							if (this.getSelectionCount() == 1) {
								var i = this.getSelectedIndexes()[0];
								var n = this.getNode(i);
								dragData.viewNodes.push(dragData.ddel = n);
								dragData.records.push(this.store.getAt(i));
								dragData.repairXY = Ext.fly(n).getXY();
							} else {
								dragData.ddel = document.createElement('div');
								dragData.ddel.className = 'multi-proxy';
								this.collectSelection(dragData);
							}
							return dragData;
						}
						return false;
					},

					// override the default repairXY.
					getRepairXY : function(e) {
						return this.dragData.repairXY;
					},

					// private
					collectSelection : function(data) {
						data.repairXY = Ext.fly(this.getSelectedNodes()[0])
								.getXY();
						if (this.preserveSelectionOrder === true) {
							Ext.each(this.getSelectedIndexes(), function(i) {
								var n = this.getNode(i);
								var dragNode = n.cloneNode(true);
								dragNode.id = Ext.id();
								data.ddel.appendChild(dragNode);
								data.records.push(this.store.getAt(i));
								data.viewNodes.push(n);
							}, this);
						} else {
							var i = 0;
							this.store.each(function(rec) {
								if (this.isSelected(i)) {
									var n = this.getNode(i);
									var dragNode = n.cloneNode(true);
									dragNode.id = Ext.id();
									data.ddel.appendChild(dragNode);
									data.records.push(this.store.getAt(i));
									data.viewNodes.push(n);
								}
								i++;
							}, this);
						}
					},

					/**
					 * Specify to which ddGroup items in this DDView may be
					 * dragged. param {String} ddGroup The DD group name to
					 * assign this view to.
					 */
					setDraggable : function(ddGroup) {
						if (ddGroup instanceof Array) {
							Ext.each(ddGroup, this.setDraggable, this);
							return;
						}
						if (this.dragZone) {
							this.dragZone.addToGroup(ddGroup);
						} else {
							this.dragZone = new Ext.dd.DragZone(this.getEl(), {
								containerScroll : true,
								ddGroup : ddGroup
							});
							// Draggability implies selection. DragZone's
							// mousedown selects the element.
							if (!this.multiSelect) {
								this.singleSelect = true;
							}

							// Wire the DragZone's handlers up to methods in
							// *this*
							this.dragZone.getDragData = this.getDragData
									.createDelegate(this);
							this.dragZone.getRepairXY = this.getRepairXY;
							this.dragZone.onEndDrag = this.onEndDrag;
						}
					},

					/**
					 * Specify from which ddGroup this DDView accepts drops.
					 * param {String} ddGroup The DD group name from which to
					 * accept drops.
					 */
					setDroppable : function(ddGroup) {
						if (ddGroup instanceof Array) {
							Ext.each(ddGroup, this.setDroppable, this);
							return;
						}
						if (this.dropZone) {
							this.dropZone.addToGroup(ddGroup);
						} else {
							this.dropZone = new Ext.dd.DropZone(this.getEl(), {
								owningView : this,
								containerScroll : true,
								ddGroup : ddGroup
							});

							// Wire the DropZone's handlers up to methods in
							// *this*
							this.dropZone.getTargetFromEvent = this.getTargetFromEvent
									.createDelegate(this);
							this.dropZone.onNodeEnter = this.onNodeEnter
									.createDelegate(this);
							this.dropZone.onNodeOver = this.onNodeOver
									.createDelegate(this);
							this.dropZone.onNodeOut = this.onNodeOut
									.createDelegate(this);
							this.dropZone.onNodeDrop = this.onNodeDrop
									.createDelegate(this);
						}
					},

					// private
					getDropPoint : function(e, n, dd) {
						if (n == this.el.dom) {
							return "above";
						}
						var t = Ext.lib.Dom.getY(n), b = t + n.offsetHeight;
						var c = t + (b - t) / 2;
						var y = Ext.lib.Event.getPageY(e);
						if (y <= c) {
							return "above";
						} else {
							return "below";
						}
					},

					// private
					isValidDropPoint : function(pt, n, data) {
						if (!data.viewNodes || (data.viewNodes.length != 1)) {
							return true;
						}
						var d = data.viewNodes[0];
						if (d == n) {
							return false;
						}
						if ((pt == "below") && (n.nextSibling == d)) {
							return false;
						}
						if ((pt == "above") && (n.previousSibling == d)) {
							return false;
						}
						return true;
					},

					// private
					onNodeEnter : function(n, dd, e, data) {
						if (this.highlightColor && (data.sourceView != this)) {
							this.el.highlight(this.highlightColor);
						}
						return false;
					},

					// private
					onNodeOver : function(n, dd, e, data) {
						var dragElClass = this.dropNotAllowed;
						var pt = this.getDropPoint(e, n, dd);
						if (this.isValidDropPoint(pt, n, data)) {
							if (this.appendOnly || this.sortField) {
								return "x-tree-drop-ok-below";
							}

							// set the insert point style on the target node
							if (pt) {
								var targetElClass;
								if (pt == "above") {
									dragElClass = n.previousSibling ? "x-tree-drop-ok-between"
											: "x-tree-drop-ok-above";
									targetElClass = "x-view-drag-insert-above";
								} else {
									dragElClass = n.nextSibling ? "x-tree-drop-ok-between"
											: "x-tree-drop-ok-below";
									targetElClass = "x-view-drag-insert-below";
								}
								if (this.lastInsertClass != targetElClass) {
									Ext.fly(n)
											.replaceClass(this.lastInsertClass,
													targetElClass);
									this.lastInsertClass = targetElClass;
								}
							}
						}
						return dragElClass;
					},

					// private
					onNodeOut : function(n, dd, e, data) {
						this.removeDropIndicators(n);
					},

					// private
					onNodeDrop : function(n, dd, e, data) {
						if (this.fireEvent("drop", this, n, dd, e, data) === false) {
							return false;
						}
						var pt = this.getDropPoint(e, n, dd);
						var insertAt = (this.appendOnly || (n == this.el.dom)) ? this.store
								.getCount()
								: n.viewIndex;
						if (pt == "below") {
							insertAt++;
						}

						// Validate if dragging within a DDView
						if (data.sourceView == this) {
							// If the first element to be inserted below is the
							// target node, remove it
							if (pt == "below") {
								if (data.viewNodes[0] == n) {
									data.viewNodes.shift();
								}
							} else { // If the last element to be inserted
										// above is the target node, remove it
								if (data.viewNodes[data.viewNodes.length - 1] == n) {
									data.viewNodes.pop();
								}
							}

							// Nothing to drop...
							if (!data.viewNodes.length) {
								return false;
							}

							// If we are moving DOWN, then because a
							// store.remove() takes place first,
							// the insertAt must be decremented.
							if (insertAt > this.store.indexOf(data.records[0])) {
								insertAt--;
							}
						}

						// Dragging from a Tree. Use the Tree's recordFromNode
						// function.
						if (data.node instanceof Ext.tree.TreeNode) {
							var r = data.node.getOwnerTree().recordFromNode(
									data.node);
							if (r) {
								data.records = [ r ];
							}
						}

						if (!data.records) {
							alert("Programming problem. Drag data contained no Records");
							return false;
						}

						for (var i = 0; i < data.records.length; i++) {
							var r = data.records[i];
							var dup = this.store.getById(r.id);
							if (dup && (dd != this.dragZone)) {
								if (!this.allowDup && !this.allowTrash) {
									Ext.fly(
											this.getNode(this.store
													.indexOf(dup))).frame(
											"red", 1);
									return true
								}
								var x = new Ext.data.Record();
								r.id = x.id;
								delete x;
							}
							if (data.copy) {
								this.store.insert(insertAt++, r.copy());
							} else {
								if (data.sourceView) {
									data.sourceView.isDirtyFlag = true;
									data.sourceView.store.remove(r);
								}
								if (!this.allowTrash)
									this.store.insert(insertAt++, r);
							}
							if (this.sortField) {
								this.store.sort(this.sortField, this.sortDir);
							}
							this.isDirtyFlag = true;
						}
						this.dragZone.cachedTarget = null;
						return true;
					},

					// private
					onEndDrag : function(data, e) {
						var d = Ext.get(this.dragData.ddel);
						if (d && d.hasClass("multi-proxy")) {
							d.remove();
							// delete this.dragData.ddel;
						}
					},

					// private
					removeDropIndicators : function(n) {
						if (n) {
							Ext.fly(n).removeClass(
									[ "x-view-drag-insert-above",
											"x-view-drag-insert-left",
											"x-view-drag-insert-right",
											"x-view-drag-insert-below" ]);
							this.lastInsertClass = "_noclass";
						}
					},

					/**
					 * Add a delete option to the DDView's context menu. param
					 * {String} imageUrl The URL of the "delete" icon image.
					 */
					setDeletable : function(imageUrl) {
						if (!this.singleSelect && !this.multiSelect) {
							this.singleSelect = true;
						}
						var c = this.getContextMenu();
						this.contextMenu.on("itemclick", function(item) {
							switch (item.id) {
							case "delete":
								this.remove(this.getSelectedIndexes());
								break;
							}
						}, this);
						this.contextMenu.add({
							icon : imageUrl
									|| AU.resolveUrl("/images/delete.gif"),
							id : "delete",
							text : AU.getMessage("deleteItem")
						});
					},

					/**
					 * Return the context menu for this DDView. return
					 * {Ext.menu.Menu} The context menu
					 */
					getContextMenu : function() {
						if (!this.contextMenu) {
							// Create the View's context menu
							this.contextMenu = new Ext.menu.Menu({
								id : this.id + "-contextmenu"
							});
							this.el.on("contextmenu", this.showContextMenu,
									this);
						}
						return this.contextMenu;
					},

					/**
					 * Disables the view's context menu.
					 */
					disableContextMenu : function() {
						if (this.contextMenu) {
							this.el.un("contextmenu", this.showContextMenu,
									this);
						}
					},

					// private
					showContextMenu : function(e, item) {
						item = this.findItemFromChild(e.getTarget());
						if (item) {
							e.stopEvent();
							this.select(this.getNode(item), this.multiSelect
									&& e.ctrlKey, true);
							this.contextMenu.showAt(e.getXY());
						}
					},

					/**
					 * Remove {link Ext.data.Record}s at the specified indices.
					 * param {Array/Number} selectedIndices The index (or Array
					 * of indices) of Records to remove.
					 */
					remove : function(selectedIndices) {
						selectedIndices = [].concat(selectedIndices);
						for (var i = 0; i < selectedIndices.length; i++) {
							var rec = this.store.getAt(selectedIndices[i]);
							this.store.remove(rec);
						}
					},

					/**
					 * Double click fires the {link #dblclick} event.
					 * Additionally, if this DDView is draggable, and there is
					 * only one other related DropZone that is in another
					 * DDView, it drops the selected node on that DDView.
					 */
					onDblClick : function(e) {
						var item = this.findItemFromChild(e.getTarget());
						if (item) {
							if (this.fireEvent("dblclick", this, this
									.indexOf(item), item, e) === false) {
								return false;
							}
							if (this.dragGroup) {
								var targets = Ext.dd.DragDropMgr.getRelated(
										this.dragZone, true);

								// Remove instances of this View's DropZone
								while (targets.indexOf(this.dropZone) !== -1) {
									targets.remove(this.dropZone);
								}

								// If there's only one other DropZone, and it is
								// owned by a DDView, then drop it in
								if ((targets.length == 1)
										&& (targets[0].owningView)) {
									this.dragZone.cachedTarget = null;
									var el = Ext.get(targets[0].getEl());
									var box = el.getBox(true);
									targets[0].onNodeDrop(el.dom, {
										target : el.dom,
										xy : [ box.x, box.y + box.height - 1 ]
									}, null, this.getDragData(e));
								}
							}
						}
					},

					// private
					onItemClick : function(item, index, e) {
						// The DragZone's mousedown->getDragData already handled
						// selection
						if (this.ignoreNextClick) {
							delete this.ignoreNextClick;
							return;
						}

						if (this.fireEvent("beforeclick", this, index, item, e) === false) {
							return false;
						}
						if (this.multiSelect || this.singleSelect) {
							if (this.multiSelect && e.shiftKey
									&& this.lastSelection) {
								this.select(this.getNodes(this
										.indexOf(this.lastSelection), index),
										false);
							} else if (this.isSelected(item) && e.ctrlKey) {
								this.deselect(item);
							} else {
								this.deselect(item);
								this.select(item, this.multiSelect
										&& (e.ctrlKey || this.simpleSelect));
								this.lastSelection = item;
							}
							e.preventDefault();
						}
						return true;
					}
				});

/**
 * @ignore Ext.ux.MultiSelect extends Ext.form.Field A control that allows
 *         selection and form submission of multiple list items. The MultiSelect
 *         control depends on the Ext.ux.DDView class to provide drag/drop
 *         capability both within the list and also between multiple MultiSelect
 *         controls (see the Ext.ux.ItemSelector).
 * 
 * history 2008-06-19 bpm Original code contributed by Toby Stuart 2008-06-19
 * bpm Docs and demo code clean up
 * 
 * constructor Create a new MultiSelect param {Object} config Configuration
 * options
 */
Ext.ux.Multiselect = Ext
		.extend(
				Ext.form.Field,
				{
					/**
					 * {String} legend Wraps the object with a fieldset and
					 * specified legend.
					 */
					/**
					 * {Store} store The {link Ext.data.Store} used by the
					 * underlying Ext.ux.DDView.
					 */
					/**
					 * {Ext.ux.DDView} view The Ext.ux.DDView used to render the
					 * multiselect list.
					 */
					/**
					 * {String/Array} dragGroup The ddgroup name(s) for the
					 * DDView's DragZone (defaults to undefined).
					 */
					/**
					 * {String/Array} dropGroup The ddgroup name(s) for the
					 * DDView's DropZone (defaults to undefined).
					 */
					/**
					 * {Object/Array} tbar The top toolbar of the control. This
					 * can be a {link Ext.Toolbar} object, a toolbar config, or
					 * an array of buttons/button configs to be added to the
					 * toolbar.
					 */
					/**
					 * {String} fieldName The name of the field to sort by when
					 * sorting is enabled.
					 */
					/**
					 * {String} appendOnly True if the list should only allow
					 * append drops when drag/drop is enabled (use for lists
					 * which are sorted, defaults to false).
					 */
					appendOnly : false,
					/**
					 * cfg {Array} dataFields Inline data definition when not
					 * using a pre-initialised store. Known to cause problems in
					 * some browswers for very long lists. Use store for large
					 * datasets.
					 */
					dataFields : [],
					/**
					 * cfg {Array} data Inline data when not using a
					 * pre-initialised store. Known to cause problems in some
					 * browswers for very long lists. Use store for large
					 * datasets.
					 */
					data : [],
					/**
					 * cfg {Number} width Width in pixels of the control
					 * (defaults to 100).
					 */
					width : 100,
					/**
					 * cfg {Number} height Height in pixels of the control
					 * (defaults to 100).
					 */
					height : 100,
					/**
					 * cfg {String/Number} displayField Name/Index of the
					 * desired display field in the dataset (defaults to 0).
					 */
					displayField : 0,
					/**
					 * cfg {String/Number} valueField Name/Index of the desired
					 * value field in the dataset (defaults to 1).
					 */
					valueField : 1,
					/**
					 * cfg {Boolean} allowBlank True to require at least one
					 * item in the list to be selected, false to allow no
					 * selection (defaults to true).
					 */
					allowBlank : true,
					/**
					 * cfg {Number} minLength Minimum number of selections
					 * allowed (defaults to 0).
					 */
					minLength : 0,
					/**
					 * cfg {Number} maxLength Maximum number of selections
					 * allowed (defaults to Number.MAX_VALUE).
					 */
					maxLength : Number.MAX_VALUE,
					/**
					 * cfg {String} blankText Default text displayed when the
					 * control contains no items (defaults to the same value as
					 * {link Ext.form.TextField#blankText}.
					 */
					blankText : Ext.form.TextField.prototype.blankText,
					/**
					 * cfg {String} minLengthText Validation message displayed
					 * when {link #minLength} is not met (defaults to 'Minimum
					 * {0} item(s) required'). The {0} token will be replaced by
					 * the value of {link #minLength}.
					 */
					minLengthText : 'Minimum {0} item(s) required',
					/**
					 * cfg {String} maxLengthText Validation message displayed
					 * when {link #maxLength} is not met (defaults to 'Maximum
					 * {0} item(s) allowed'). The {0} token will be replaced by
					 * the value of {link #maxLength}.
					 */
					maxLengthText : 'Maximum {0} item(s) allowed',
					/**
					 * cfg {String} delimiter The string used to delimit between
					 * items when set or returned as a string of values
					 * (defaults to ',').
					 */
					delimiter : ',',

					// DDView settings
					copy : false,
					allowDup : false,
					allowTrash : false,
					focusClass : undefined,
					sortDir : 'ASC',

					// private
					defaultAutoCreate : {
						tag : "div"
					},

					// private
					initComponent : function() {
						Ext.ux.Multiselect.superclass.initComponent.call(this);
						this.addEvents({
							'dblclick' : true,
							'click' : true,
							'change' : true,
							'drop' : true
						});
					},

					// private
					onRender : function(ct, position) {
						Ext.ux.Multiselect.superclass.onRender.call(this, ct,
								position);

						var cls = 'ux-mselect';
						var fs = new Ext.form.FieldSet({
							renderTo : this.el,
							title : this.legend,
							height : this.height,
							width : this.width,
							style : "padding:0;",
							tbar : this.tbar
						});
						// if(!this.legend)fs.el.down('.'+fs.headerCls).remove();
						fs.body.addClass(cls);

						var tpl = '<tpl for="."><div class="' + cls + '-item';
						if (Ext.isIE || Ext.isIE7) {
							tpl += '" unselectable=on';
						} else {
							tpl += ' x-unselectable"';
						}
						tpl += '>{' + this.displayField + '}</div></tpl>';

						if (!this.store) {
							this.store = new Ext.data.SimpleStore({
								fields : this.dataFields,
								data : this.data
							});
						}

						this.view = new Ext.ux.DDView({
							multiSelect : true,
							simpleSelect : true,
							store : this.store,
							selectedClass : cls + "-selected",
							tpl : tpl,
							allowDup : this.allowDup,
							copy : this.copy,
							allowTrash : this.allowTrash,
							dragGroup : this.dragGroup,
							dropGroup : this.dropGroup,
							itemSelector : "." + cls + "-item",
							isFormField : false,
							applyTo : fs.body,
							appendOnly : this.appendOnly,
							sortField : this.sortField,
							sortDir : this.sortDir
						});

						fs.add(this.view);

						this.view.on('click', this.onViewClick, this);
						this.view.on('beforeClick', this.onViewBeforeClick,
								this);
						this.view.on('dblclick', this.onViewDblClick, this);
						this.view.on('drop', function(ddView, n, dd, e, data) {
							return this.fireEvent("drop", ddView, n, dd, e,
									data);
						}, this);

						this.hiddenName = this.name;
						var hiddenTag = {
							tag : "input",
							type : "hidden",
							value : "",
							name : this.name
						};
						if (this.isFormField) {
							this.hiddenField = this.el.createChild(hiddenTag);
						} else {
							this.hiddenField = Ext.get(document.body)
									.createChild(hiddenTag);
						}
						fs.doLayout();
					},

					// private
					initValue : Ext.emptyFn,

					// private
					onViewClick : function(vw, index, node, e) {
						var arrayIndex = this.preClickSelections.indexOf(index);
						if (arrayIndex != -1) {
							this.preClickSelections.splice(arrayIndex, 1);
							this.view.clearSelections(true);
							this.view.select(this.preClickSelections);
						}
						this.fireEvent('change', this, this.getValue(),
								this.hiddenField.dom.value);
						this.hiddenField.dom.value = this.getValue();
						this.fireEvent('click', this, e);
						this.validate();
					},

					// private
					onViewBeforeClick : function(vw, index, node, e) {
						this.preClickSelections = this.view
								.getSelectedIndexes();
						if (this.disabled) {
							return false;
						}
					},

					// private
					onViewDblClick : function(vw, index, node, e) {
						return this.fireEvent('dblclick', vw, index, node, e);
					},

					/**
					 * Returns an array of data values for the selected items in
					 * the list. The values will be separated by {link
					 * #delimiter}. return {Array} value An array of string data
					 * values
					 */
					getValue : function(valueField) {
						var returnArray = [];
						var selectionsArray = this.view.getSelectedIndexes();
						if (selectionsArray.length == 0) {
							return '';
						}
						for (var i = 0; i < selectionsArray.length; i++) {
							returnArray.push(this.store.getAt(
									selectionsArray[i]).get(
									((valueField != null) ? valueField
											: this.valueField)));
						}
						return returnArray.join(this.delimiter);
					},

					/**
					 * Sets a delimited string (using {link #delimiter}) or
					 * array of data values into the list. param {String/Array}
					 * values The values to set
					 */
					setValue : function(values) {
						var index;
						var selections = [];
						this.view.clearSelections();
						this.hiddenField.dom.value = '';

						if (!values || (values == '')) {
							return;
						}

						if (!(values instanceof Array)) {
							values = values.split(this.delimiter);
						}
						for (var i = 0; i < values.length; i++) {
							index = this.view.store.indexOf(this.view.store
									.query(
											this.valueField,
											new RegExp('^' + values[i] + '$',
													"i")).itemAt(0));
							selections.push(index);
						}
						this.view.select(selections);
						this.hiddenField.dom.value = this.getValue();
						this.validate();
					},

					// inherit docs
					reset : function() {
						this.setValue('');
					},

					// inherit docs
					getRawValue : function(valueField) {
						var tmp = this.getValue(valueField);
						if (tmp.length) {
							tmp = tmp.split(this.delimiter);
						} else {
							tmp = [];
						}
						return tmp;
					},

					// inherit docs
					setRawValue : function(values) {
						setValue(values);
					},

					// inherit docs
					validateValue : function(value) {
						if (value.length < 1) { // if it has no value
							if (this.allowBlank) {
								this.clearInvalid();
								return true;
							} else {
								this.markInvalid(this.blankText);
								return false;
							}
						}
						if (value.length < this.minLength) {
							this.markInvalid(String.format(this.minLengthText,
									this.minLength));
							return false;
						}
						if (value.length > this.maxLength) {
							this.markInvalid(String.format(this.maxLengthText,
									this.maxLength));
							return false;
						}
						return true;
					}
				});

Ext.reg("multiselect", Ext.ux.Multiselect);
Wonders.form.ListBox = Ext.ux.Multiselect;

/**
 * @ignore 滑动条
 */
Ext.Slider = Ext
		.extend(
				Ext.BoxComponent,
				{
					vertical : false,
					minValue : 0,
					maxValue : 100,
					keyIncrement : 1,
					increment : 0,
					clickRange : [ 5, 15 ],
					clickToChange : true,
					animate : true,
					dragging : false,
					initComponent : function() {
						if (this.value === undefined) {
							this.value = this.minValue
						}
						Ext.Slider.superclass.initComponent.call(this);
						this.keyIncrement = Math.max(this.increment,
								this.keyIncrement);
						this.addEvents("beforechange", "change",
								"changecomplete", "dragstart", "drag",
								"dragend");
						if (this.vertical) {
							Ext.apply(this, Ext.Slider.Vertical)
						}
					},
					onRender : function() {
						this.autoEl = {
							cls : "x-slider "
									+ (this.vertical ? "x-slider-vert"
											: "x-slider-horz"),
							cn : {
								cls : "x-slider-end",
								cn : {
									cls : "x-slider-inner",
									cn : [ {
										cls : "x-slider-thumb"
									}, {
										tag : "a",
										cls : "x-slider-focus",
										href : "#",
										tabIndex : "-1",
										hidefocus : "on"
									} ]
								}
							}
						};
						Ext.Slider.superclass.onRender.apply(this, arguments);
						this.endEl = this.el.first();
						this.innerEl = this.endEl.first();
						this.thumb = this.innerEl.first();
						this.halfThumb = (this.vertical ? this.thumb
								.getHeight() : this.thumb.getWidth()) / 2;
						this.focusEl = this.thumb.next();
						this.initEvents()
					},
					initEvents : function() {
						this.thumb.addClassOnOver("x-slider-thumb-over");
						this.el.on('mousedown', this.onMouseDown, this);
						this.el.on('keydown', this.onKeyDown, this);
						this.focusEl.swallowEvent("click", true);
						this.tracker = new Ext.dd.DragTracker({
							onBeforeStart : this.onBeforeDragStart
									.createDelegate(this),
							onStart : this.onDragStart.createDelegate(this),
							onDrag : this.onDrag.createDelegate(this),
							onEnd : this.onDragEnd.createDelegate(this),
							tolerance : 3,
							autoStart : 300
						});
						this.tracker.initEl(this.thumb);
						this.on("beforedestroy", this.tracker.destroy,
								this.tracker)
					},
					onMouseDown : function(B) {
						if (this.disabled) {
							return
						}
						if (this.clickToChange && B.target != this.thumb.dom) {
							var A = this.innerEl.translatePoints(B.getXY());
							this.onClickChange(A)
						}
						this.focus()
					},
					onClickChange : function(A) {
						if (A.top > this.clickRange[0]
								&& A.top < this.clickRange[1]) {
							this.setValue(
									Math.round(this.reverseValue(A.left)),
									undefined, true)
						}
					},
					onKeyDown : function(B) {
						if (this.disabled) {
							B.preventDefault();
							return
						}
						var A = B.getKey();
						switch (A) {
						case B.UP:
						case B.RIGHT:
							B.stopEvent();
							if (B.ctrlKey) {
								this.setValue(this.maxValue, undefined, true)
							} else {
								this.setValue(this.value + this.keyIncrement,
										undefined, true)
							}
							break;
						case B.DOWN:
						case B.LEFT:
							B.stopEvent();
							if (B.ctrlKey) {
								this.setValue(this.minValue, undefined, true)
							} else {
								this.setValue(this.value - this.keyIncrement,
										undefined, true)
							}
							break;
						default:
							B.preventDefault()
						}
					},
					doSnap : function(B) {
						if (!this.increment || this.increment == 1 || !B) {
							return B
						}
						var D = B, C = this.increment;
						var A = B % C;
						if (A > 0) {
							if (A > (C / 2)) {
								D = B + (C - A)
							} else {
								D = B - A
							}
						}
						return D.constrain(this.minValue, this.maxValue)
					},
					afterRender : function() {
						Ext.Slider.superclass.afterRender
								.apply(this, arguments);
						if (this.value !== undefined) {
							var A = this.normalizeValue(this.value);
							if (A !== this.value) {
								delete this.value;
								this.setValue(A, false)
							} else {
								this.moveThumb(this.translateValue(A), false)
							}
						}
					},
					getRatio : function() {
						var A = this.innerEl.getWidth();
						var B = this.maxValue - this.minValue;
						return B == 0 ? A : (A / B)
					},
					normalizeValue : function(A) {
						if (typeof A != "number") {
							A = parseInt(A)
						}
						A = Math.round(A);
						A = this.doSnap(A);
						A = A.constrain(this.minValue, this.maxValue);
						return A
					},
					setValue : function(B, A, C) {
						B = this.normalizeValue(B);
						if (B !== this.value
								&& this.fireEvent("beforechange", this, B,
										this.value) !== false) {
							this.value = B;
							this.moveThumb(this.translateValue(B), A !== false);
							this.fireEvent("change", this, B);
							if (C) {
								this.fireEvent("changecomplete", this, B)
							}
						}
					},
					translateValue : function(A) {
						var B = this.getRatio();
						return (A * B) - (this.minValue * B) - this.halfThumb
					},
					reverseValue : function(B) {
						var A = this.getRatio();
						return (B + this.halfThumb + (this.minValue * A)) / A
					},
					moveThumb : function(B, A) {
						if (!A || this.animate === false) {
							this.thumb.setLeft(B)
						} else {
							this.thumb.shift({
								left : B,
								stopFx : true,
								duration : 0.35
							})
						}
					},
					focus : function() {
						this.focusEl.focus(10)
					},
					onBeforeDragStart : function(A) {
						return !this.disabled
					},
					onDragStart : function(A) {
						this.thumb.addClass("x-slider-thumb-drag");
						this.dragging = true;
						this.dragStartValue = this.value;
						this.fireEvent("dragstart", this, A)
					},
					onDrag : function(A) {
						var B = this.innerEl.translatePoints(this.tracker
								.getXY());
						this.setValue(Math.round(this.reverseValue(B.left)),
								false);
						this.fireEvent("drag", this, A)
					},
					onDragEnd : function(A) {
						this.thumb.removeClass("x-slider-thumb-drag");
						this.dragging = false;
						this.fireEvent("dragend", this, A);
						if (this.dragStartValue != this.value) {
							this.fireEvent("changecomplete", this, this.value)
						}
					},
					onResize : function(A, B) {
						this.innerEl.setWidth(A
								- (this.el.getPadding("l") + this.endEl
										.getPadding("r")));
						this.syncThumb()
					},
					syncThumb : function() {
						if (this.rendered) {
							this.moveThumb(this.translateValue(this.value))
						}
					},
					getValue : function() {
						return this.value
					}
				});
Ext.reg("slider", Ext.Slider);
/**
 * @ignore
 */
Ext.Slider.Vertical = {
	/**
	 * @ignore
	 */
	onResize : function(A, B) {
		this.innerEl.setHeight(B
				- (this.el.getPadding("t") + this.endEl.getPadding("b")));
		this.syncThumb()
	},
	/**
	 * @ignore
	 */
	getRatio : function() {
		var B = this.innerEl.getHeight();
		var A = this.maxValue - this.minValue;
		return B / A
	},
	/**
	 * @ignore
	 */
	moveThumb : function(B, A) {
		if (!A || this.animate === false) {
			this.thumb.setBottom(B)
		} else {
			this.thumb.shift({
				bottom : B,
				stopFx : true,
				duration : 0.35
			})
		}
	},
	/**
	 * @ignore
	 */
	onDrag : function(B) {
		var C = this.innerEl.translatePoints(this.tracker.getXY());
		var A = this.innerEl.getHeight() - C.top;
		this.setValue(Math.round(A / this.getRatio()), false);
		this.fireEvent("drag", this, B)
	},
	/**
	 * @ignore
	 */
	onClickChange : function(B) {
		if (B.left > this.clickRange[0] && B.left < this.clickRange[1]) {
			var A = this.innerEl.getHeight() - B.top;
			this.setValue(Math.round(A / this.getRatio()), undefined, true)
		}
	}
};

/**
 * @ignore Ext.ux.SliderTip extends Ext.Tip Simple plugin for using an Ext.Tip
 *         with a slider to show the slider value
 */
Ext.ux.SliderTip = Ext.extend(Ext.Tip, {
	minWidth : 10,
	offsets : [ 0, -10 ],
	init : function(slider) {
		slider.on('dragstart', this.onSlide, this);
		slider.on('drag', this.onSlide, this);
		slider.on('dragend', this.hide, this);
		slider.on('destroy', this.destroy, this);
	},

	onSlide : function(slider) {
		this.show();
		this.body.update(this.getText(slider));

		var bw = this.body.getTextWidth();
		if (this.title) {
			bw = Math.max(bw, this.header.child('span')
					.getTextWidth(this.title));
		}
		bw += this.getFrameWidth() + (this.closable ? 20 : 0)
				+ this.body.getPadding("lr");
		this.setWidth(bw.constrain(this.minWidth, this.maxWidth));

		// IE7 repaint bug on initial show
		if (Ext.isIE7 && !this.repainted) {
			this.el.repaint();
			this.repainted = true;
		}

		this.width = 100;
		this.el.alignTo(slider.thumb, 'b-t?', this.offsets);
	},

	getText : function(slider) {
		return slider.getValue();
	}
});

/*******************************************************************************
 * 表单组件方法重写
 ******************************************************************************/

/**
 * Ext.form.Field Override class definitions
 */
Ext.apply(Ext.form.Field.prototype, {

	markInvalid : function(msg) {

		// support to get invalidText
		this.invalidText = msg || this.invalidText;

		if (!this.rendered || this.preventMark) { // not rendered
			return;
		}
		this.el.addClass(this.invalidClass);
		msg = this.invalidText;
		switch (this.msgTarget) {
		case 'qtip':
			this.el.dom.qtip = msg;
			this.el.dom.qclass = 'x-form-invalid-tip';
			if (Ext.QuickTips) { // fix for floating editors interacting
				// with DND
				Ext.QuickTips.enable();
			}
			break;
		case 'title':
			this.el.dom.title = msg;
			break;
		case 'under':
			if (!this.errorEl) {
				var elp = this.el.findParent('.x-form-element', 5, true);
				this.errorEl = elp.createChild({
					cls : 'x-form-invalid-msg'
				});
				this.errorEl.setWidth(elp.getWidth(true) - 20);
			}
			this.errorEl.update(msg);
			Ext.form.Field.msgFx[this.msgFx].show(this.errorEl, this);
			break;
		case 'side':
			if (!this.errorIcon) {
				var elp = this.el.findParent('.x-form-element', 5, true);
				this.errorIcon = elp.createChild({
					cls : 'x-form-invalid-icon'
				});
			}
			this.alignErrorIcon();
			this.errorIcon.dom.qtip = msg;
			this.errorIcon.dom.qclass = 'x-form-invalid-tip';
			this.errorIcon.show();
			this.on('resize', this.alignErrorIcon, this);
			break;
		default:
			var t = Ext.getDom(this.msgTarget);
			t.innerHTML = msg;
			t.style.display = this.msgDisplay;
			break;
		}
		this.fireEvent('invalid', this, msg);
	}

})

/**
 * @ignore 修改提交方法不提交emptyText Ext.form.Action.Submit Override success method
 * 
 * author Wang yuxin
 */
Ext.apply(Ext.form.Action.Submit.prototype, {

	success : function(response) {
		var result = this.processResponse(response);
		if (result === true || result.success) {
			this.form.afterAction(this, true);
			return;
		}
		if (result.errors) {
			// remove markInvalid for server_invalid
			// this.form.markInvalid(result.errors);
			this.failureType = Ext.form.Action.SERVER_INVALID;
		}
		this.form.afterAction(this, false);
	},

	run : function() {
		var o = this.options;
		var method = this.getMethod();
		var isGet = method == 'GET';
		if (o.clientValidation === false || this.form.isValid()) {
			// if (o.submitEmptyText === false) {
			var fields = this.form.items, emptyFields = [];
			fields.each(function(f) {
				if (f.el.getValue() == f.emptyText) {
					emptyFields.push(f);
					f.el.dom.value = "";
				}
			});
			// }
			Ext.Ajax.request(Ext.apply(this.createCallback(o), {
				form : this.form.el.dom,
				url : this.getUrl(isGet),
				method : method,
				headers : o.headers,
				params : !isGet ? this.getParams() : null,
				isUpload : this.form.fileUpload
			}));
			// if (o.submitEmptyText === false) {
			Ext.each(emptyFields, function(f) {
				if (f.applyEmptyText) {
					f.applyEmptyText();
				}
			});
			// }
		} else if (o.clientValidation !== false) {
			this.failureType = Ext.form.Action.CLIENT_INVALID;
			this.form.afterAction(this, false);
		}
	}

})

// private
/**
 * 
 * @ignore
 * 
 */
setTriggerDisable = function() {
	return false;
}

// private
/**
 * @ignore
 */
setTriggerStyle = function(t, readOnly) {
	if (readOnly) {
		var w = t.el.getWidth();
		if (typeof w == 'number' && w != 0) {
			if (Ext.isIE) {
				t.el.setWidth(t.adjustWidth('input', w + t.trigger.getWidth()
						+ 3));
			} else {
				t.el.setWidth(t.adjustWidth('input', w + t.trigger.getWidth()));
			}
		}
		t.trigger.setDisplayed(false);
	}

	if (!readOnly) {
		if (t.trigger.getWidth() == 0) {
			t.trigger.setDisplayed(true);
			var w = t.el.getWidth();
			if (typeof w == 'number' && w != 0) {
				if (Ext.isIE) {
					t.el.setWidth(t.adjustWidth('input', w
							- t.trigger.getWidth() + 3));
					t.wrap.setWidth(t.el.getWidth() + t.trigger.getWidth());
				} else {
					t.el.setWidth(t.adjustWidth('input', w
							- t.trigger.getWidth()));
					t.wrap.setWidth(t.el.getWidth() + t.trigger.getWidth());
				}
			}
			var A;
			if (Ext.isIE && t.el.getY() != (A = t.trigger.getY())
					&& t.trigger.isVisible()) {
				t.el.position();
				t.el.setY(A)
			}
		}
	}
}

/**
 * @ignore 设置输入字段是否为只读
 */
Ext.form.Field.prototype.setReadOnly = function(readOnly) {
	this.readOnly = readOnly;
	if (this.readOnly) {
		this.el.dom.readOnly = readOnly;
		this.el.addClass("x-item-readOnly");
		// 设置下拉按钮不可用
		if (this.getXTypes().indexOf('trigger') != -1) {
			this.addListener("beforequery", setTriggerDisable);
			setTriggerStyle(this, readOnly);
		}
	}
	if (!this.readOnly) {
		this.el.dom.readOnly = readOnly;
		this.el.removeClass("x-item-readOnly");
		// 还原下拉按钮可用
		if (this.getXTypes().indexOf('trigger') != -1) {
			this.removeListener("beforequery", setTriggerDisable);
			setTriggerStyle(this, readOnly);
		}
	}
}

/**
 * Ext.form.Checkbox Override class definitions
 */
Ext
		.apply(Ext.form.Checkbox.prototype,
				{

					// override setValue method
					setValue : function(value) {
						if (typeof value != 'boolean') {
							var array = new Array();
							array = value.split(',');
							for (var i = 0; i < array.length; i++) {
								var targetCheckbox = this.el.up('form').child(
										'input[@name=' + this.el.dom.name
												+ '][@value=' + array[i] + ']',
										true);
								if (targetCheckbox != null) {
									targetCheckbox.checked = true;
								}
							}
						} else {
							this.checked = (value === true || value === 'true'
									|| value == '1' || String(value)
									.toLowerCase() == 'on');
							if (this.el && this.el.dom) {
								this.el.dom.checked = this.checked;
								this.el.dom.defaultChecked = this.checked;
							}
						}
						this.fireEvent("check", this, this.checked);
					},

					// override markInvalid method
					markInvalid : function(msg) {
						if (!this.rendered || this.preventMark) { // not
																	// rendered
							return;
						}
					},

					// override clearInvalid method
					clearInvalid : function() {
						if (!this.rendered || this.preventMark) { // not
																	// rendered
							return;
						}
					},

					// add checkbox and radio required validation
					validateValue : function(value) {
						if (!this.allowBlank) {
							var needAlert = true;
							if (this.el.up('form')) {
								var checkItems = this.el.up('form')
										.query(
												'input[@name='
														+ this.el.dom.name
														+ ']');
								for ( var checkItem in checkItems) {
									if (checkItems[checkItem].checked) {
										needAlert = false;
									}
								}
								if (needAlert) {
									this.markInvalid('"' + this.fieldLabel
											+ '" \u4e3a\u5fc5\u586b\u9879!');
									return false;
								} else {
									this.clearInvalid();
									return true;
								}
							}
						}
						return true;
					}

				});

/**
 * Ext.form.Radio Override class definitions
 */
Ext.apply(Ext.form.Radio.prototype, {

	// override markInvalid method
	markInvalid : function(msg) {
		if (!this.rendered || this.preventMark) { // not rendered
			return;
		}
	},

	// override clearInvalid method
	clearInvalid : function() {
		if (!this.rendered || this.preventMark) { // not rendered
			return;
		}
	}

})

/**
 * Ext.form.VTypes Custom validation definitions
 */

// custom Vtype for vtype:'account'
Ext.apply(Ext.form.VTypes, {
	// vtype validation function
	account : function(v) {
		return /^[a-zA-Z0-9_\-]+$/.test(v);
	},
	// vtype Text property: The error text to display when the validation
	// function returns false
	accountText : 'This field should only contain letters, numbers, _ and -',
	// vtype Mask property: The keystroke filter mask
	accountMask : /[a-z0-9_\-]/i
});

// custom Vtype for vtype:'zipcode'
Ext.apply(Ext.form.VTypes, {
	// vtype validation function
	zipcode : function(v) {
		return /^[0-9]\d{5}(?!\d)$/.test(v);
	},
	// vtype Text property: The error text to display when the validation
	// function returns false
	zipcodeText : 'This field should be a zipcode such as: 200940',
	// vtype Mask property: The keystroke filter mask
	zipcodeMask : /[0-9]/
});

// custom Vtype for vtype:'idcard'
var idcardText = '';
// Vtype for vtype:'CNcharacter'
Ext.apply(Ext.form.VTypes, {
	// vtype validation function
	idcard : function(value) {
		if (value && value != "") {
			if (value.length != 15 && value.length != 18) {
				idcardText = '\u957f\u5ea6\u5fc5\u987b\u4e3a15\u621618\u4f4d';
				Ext.form.VTypes['idcardText'] = idcardText;
				return false;
			}
			var patten1 = "^\\d{15}$";
			var patten2 = "^\\d{17}[0123456789X]$";
			if (!new RegExp(patten1, "g").test(value)
					&& !new RegExp(patten2, "g").test(value)) {
				idcardText = '\u53ea\u80fd\u5305\u542b\u6570\u5b57\u6216X';
				Ext.form.VTypes['idcardText'] = idcardText;
				return false;
			}
			var strID18 = Wonders.utils.idCardTo18(value);
			var csrqstr = strID18.substr(6, 8);
			var year = parseInt(csrqstr.substr(0, 4), 10);
			var month = parseInt(csrqstr.substr(4, 2), 10) - 1;
			var date = parseInt(csrqstr.substr(6, 2), 10);

			var csrq = new Date(year, month, date);
			if (year != csrq.getFullYear() || month != csrq.getMonth()
					|| date != csrq.getDate()) {
				idcardText = '\u8eab\u4efd\u8bc1\u7684\u51fa\u751f\u65e5\u671f'
						+ csrqstr + '\u6709\u8bef';
				Ext.form.VTypes['idcardText'] = idcardText;
				return false;
			}
			if (value.length == 18 && value != strID18) {
				idcardText = '\u6b63\u786e\u7684\u5e94\u4e3a' + strID18;
				Ext.form.VTypes['idcardText'] = idcardText;
				return false;
			}
			month = month + 1;
			return true;
		} else {
			return true;
		}
		;
	},
	// vtype Text property: The error text to display when the validation
	// function returns false
	idcardText : idcardText,
	// vtype Mask property: The keystroke filter mask
	idcardMask : /[x0-9]/i
});

// custom Vtype for vtype:'CNcharacter'
Ext.apply(Ext.form.VTypes, {
	CNcharacter : function(value) {
		var CNcharacter = /[^\x00-\xff]/g;
		return CNcharacter.test(value);
	},
	CNcharacterText : '',
	CNcharacterMask : /[^\x00-\xff]/g
});

// custom Vtype for vtype:'daterange'
Ext.apply(Ext.form.VTypes, {
	daterange : function(val, field) {
		var date = field.parseDate(val);

		if (!date) {
			return;
		}
		if (field.startDateField
				&& (!this.dateRangeMax || (date.getTime() != this.dateRangeMax
						.getTime()))) {
			var start = Ext.getCmp(field.startDateField);
			start.setMaxValue(date);
			start.validate();
			this.dateRangeMax = date;
		} else if (field.endDateField
				&& (!this.dateRangeMin || (date.getTime() != this.dateRangeMin
						.getTime()))) {
			var end = Ext.getCmp(field.endDateField);
			end.setMinValue(date);
			end.validate();
			this.dateRangeMin = date;
		}
		/*
		 * Always return true since we're only using this vtype to set the
		 * min/max allowed values (these are tested for after the vtype test)
		 */
		return true;
	}
});

/**
 * 添加判断是否需要把中文字符算成两个字节的属性，并修改取得长度的方法 CNCharacter:false, var
 * length=value.replace(/[^\x00-\xff]/g,"xx").length;
 */
Ext
		.apply(
				Ext.form.TextField.prototype,
				{

					cnCharacter : false,

					oldvalue : "",

					validateValue : function(value) {
						if (this.cnCharacter == false) {
							var length = value.length;
						} else {
							var length = value.replace(/[^\x00-\xff]/g, "xx").length;
						}
						if (length < 1 || value === this.emptyText) {
							if (this.allowBlank) {
								this.clearInvalid();
								return true;
							} else {
								this.markInvalid(this.blankText);
								return false;
							}
						}
						if (length < this.minLength) {
							this.markInvalid(String.format(this.minLengthText,
									this.minLength));
							return false;
						}
						if (length > this.maxLength) {
							this.markInvalid(String.format(this.maxLengthText,
									this.maxLength));
							return false;
						}
						if (this.vtype) {
							var vt = Ext.form.VTypes;
							if (!vt[this.vtype](value, this)) {
								this.markInvalid(this.vtypeText
										|| vt[this.vtype + 'Text']);
								return false;
							}
						}
						if (typeof this.validator == "function") {
							var msg = this.validator(value);
							if (msg !== true) {
								this.markInvalid(msg);
								return false;
							}
						}
						if (this.regex && !this.regex.test(value)) {
							this.markInvalid(this.regexText);
							return false;
						}
						return true;
					},

					// 若超过最大值，则不允许输入字符
					initValue : function() {
						if (this.value !== undefined) {
							this.setValue(this.value);
						} else if (this.el.dom.value.length > 0) {
							this.setValue(this.el.dom.value);
						}

						if (!isNaN(this.maxLength) && (this.maxLength * 1) > 0
								&& (this.maxLength != Number.MAX_VALUE)) {
							this.el.dom.maxLength = this.maxLength * 1;

							// 对于中文字符和全角字符进行录入限制
							var textObj = this;
							var textEl = this.el.dom;
							if (Ext.isIE) {
								this.el.dom.onpropertychange = function() {
									textObj.noPermitInput(textObj, textEl);
								}
							} else {
								this.el.dom.addEventListener('input', function(
										o) {
									textObj.noPermitInput(textObj, textEl);
								}, true);
							}
						}
					},

					// private
					noPermitInput : function(textObj, textEl) {
						if (textObj.cnCharacter == true
								&& (textEl.value.length * 1) > 0) {
							var length = textEl.value.replace(/[^\x00-\xff]/g,
									"xx").length;
							if (length > textEl.maxLength) {
								textEl.value = textObj.oldvalue;
							} else {
								textObj.oldvalue = textEl.value;
							}
						}
					},

					// private
					onDisable : function() {
						Ext.form.TextField.superclass.onDisable.call(this);
						if (Ext.isIE) {
							this.el.dom.unselectable = 'on';
						}
					},

					// private
					onEnable : function() {
						Ext.form.TextField.superclass.onEnable.call(this);
						if (Ext.isIE) {
							this.el.dom.unselectable = '';
						}
					}
				})

/**
 * Ext.form.ComboBox Override class definitions
 */
Ext
		.apply(
				Ext.form.ComboBox.prototype,
				{
					initEvents : function() {
						Ext.form.ComboBox.superclass.initEvents.call(this);

						this.keyNav = new Ext.KeyNav(this.el,
								{
									"up" : function(e) {
										this.inKeyMode = true;
										this.selectPrev();
									},

									"down" : function(e) {
										if (!this.isExpanded()) {
											this.onTriggerClick();
										} else {
											this.inKeyMode = true;
											this.selectNext();
										}
									},

									"enter" : function(e) {
										this.onViewClick();
										this.delayedCheck = true;
										this.unsetDelayCheck.defer(10, this);
									},

									"esc" : function(e) {
										this.collapse();
									},

									"tab" : function(e) {
										this.onViewClick(false);
										return true;
									},

									scope : this,

									doRelay : function(foo, bar, hname) {
										if (hname == 'down'
												|| this.scope.isExpanded()) {
											return Ext.KeyNav.prototype.doRelay
													.apply(this, arguments);
										}
										return true;
									},

									forceKeyDown : true
								});
						this.queryDelay = Math.max(this.queryDelay || 10,
								this.mode == 'local' ? 10 : 250);
						this.dqTask = new Ext.util.DelayedTask(this.initQuery,
								this);
						if (this.typeAhead) {
							this.taTask = new Ext.util.DelayedTask(
									this.onTypeAhead, this);
						}
						if (this.editable !== false) {
							this.el.on("cut", this.onClipboard, this);
							this.el.on("paste", this.onClipboard, this);
							this.el.on("keyup", this.onKeyUp, this);
						}
						if (this.forceSelection) {
							this.on('blur', this.doForce, this);
						}
					},

					onRender : function(ct, position) {
						Ext.form.ComboBox.superclass.onRender.call(this, ct,
								position);
						if (this.hiddenName) {
							this.hiddenField = this.el.insertSibling({
								tag : "input",
								type : "hidden",
								name : this.hiddenName,
								id : (this.hiddenId || this.hiddenName)
							}, "before", true);
							this.hiddenField.value = this.hiddenValue !== undefined ? this.hiddenValue
									: this.value !== undefined ? this.value
											: "";
							this.el.dom.removeAttribute("name")
						}
						if (Ext.isGecko) {
							this.el.dom.setAttribute("autocomplete", "off")
						}
						if (!this.lazyInit) {
							this.initList()
						} else {
							this.on("focus", this.initList, this, {
								single : true
							})
						}
						if (!this.editable) {
							this.editable = true;
							this.setEditable(false)
						}
						Ext.EventManager.onWindowResize(function() {
							this.onResize(this.width, this.height)
						}, this, [ false ]);
					},

					restrictHeight : function() {
						this.innerList.dom.style.height = '';
						var inner = this.innerList.dom;
						var pad = this.list.getFrameWidth('tb')
								+ (this.resizable ? this.handleHeight : 0)
								+ this.assetHeight;
						var h = Math.max(inner.clientHeight,
								inner.offsetHeight, inner.scrollHeight);
						var ha = this.getPosition()[1]
								- Ext.getBody().getScroll().top;
						var hb = Ext.lib.Dom.getViewHeight() - ha
								- this.getSize().height;
						var space = Math.max(ha, hb, this.minHeight || 0)
								- this.list.shadowOffset - pad - 5;
						if (inner.scrollWidth > inner.clientWidth)
							h = h + 17;
						h = Math.min(h, space, this.maxHeight);

						this.innerList.setHeight(h);
						this.list.beginUpdate();
						this.list.setHeight(h + pad);
						this.list.alignTo(this.wrap, this.listAlign);
						this.list.endUpdate();
					},

					onLoad : function() {
						if (!this.hasFocus) {
							return;
						}
						if (this.store.getCount() > 0) {
							this.expand();
							this.restrictHeight();
							// adjust table width
							if (this.innerList.dom.scrollHeight > this.innerList.dom.clientHeight
									&& this.innerList.dom.scrollWidth > this.innerList.dom.clientWidth) {
								if (this.innerList.dom.children.length > 0) {
									var child = this.innerList.dom.children[0];
									if (child.tagName.toLowerCase() == "table") {
										child.width = this.innerList.dom.clientWidth;
									}
								}
							}
							if (this.lastQuery == this.allQuery) {
								if (this.editable) {
									this.el.dom.select();
								}
								if (!this.selectByValue(this.value, true)) {
									this.select(0, true);
								}
							} else {
								this.selectNext();
								if (this.typeAhead
										&& this.lastKey != Ext.EventObject.BACKSPACE
										&& this.lastKey != Ext.EventObject.DELETE) {
									this.taTask.delay(this.typeAheadDelay);
								}
							}
						} else {
							this.onEmptyResults();
						}
						// this.el.focus();
					},

					onClipboard : function(e) {
						if (this.editable !== false && !this.isExpanded()) {
							this.dqTask.delay(this.queryDelay);
						}
					},
					setValue : function(v) {
						var text = v;
						if (this.valueField) {
							var r = this.findRecord(this.valueField, v);
							if (r) {
								text = r.data[this.displayField];
							} else if (this.valueNotFoundText !== undefined) {
								text = this.valueNotFoundText;
							}
						}
						this.lastSelectionText = text;
						if (this.hiddenField) {
							this.hiddenField.value = v;
						}
						Ext.form.ComboBox.superclass.setValue.call(this, text);
						this.value = v;
						// 添加此句，记录处于选择状态的record，用于formSubmit方法
						this.selectedIndex = undefined;
					},
					onKeyUp : function(e) {
						if (this.editable !== false) {
							// 添加此句判断，记录手动输入对于combobox的影响
							if (this.inKeyMode == false) {
								this.selectedIndex = -1;
							}
							if (!e.isSpecialKey()) {
								this.lastKey = e.getKey();
								this.dqTask.delay(this.queryDelay);
							} else if (e.getKey() == 13 && !this.isExpanded()) {
								// 添加限制条件
								var index = this.view.getSelectedIndexes()[0];
								if (index != undefined) {
									var r = this.store.getAt(index);
									if (r
											&& r.get(this.displayField) != this
													.getRawValue()) {
										this.doQuery(this.getRawValue(), true);
									}
								} else {
									this.doQuery(this.getRawValue(), true);
								}
							}
						}
					},

					onFocus : function() {
						Ext.form.ComboBox.superclass.onFocus.call(this);
						if (this.editable !== false) {
							this.selectText();
						}
					}
				});

/**
 * Ext.form.NumberField Override class definitions
 */
Ext.apply(Ext.form.NumberField.prototype,
		{
			setValue : function(v) {
				v = parseFloat(v);
				v = typeof v == 'number' ? v : String(v).replace(
						this.decimalSeparator, ".");
				v = isNaN(v) ? '' : String(v).replace(".",
						this.decimalSeparator);
				v = isNaN(v) ? '' : this.fixPrecision(String(v).replace(".",
						this.decimalSeparator));
				Ext.form.NumberField.superclass.setValue.call(this, v);
			},

			// private
			fixPrecision : function(value) {
				var nan = isNaN(value);
				if (!this.allowDecimals || this.decimalPrecision == -1 || nan
						|| !value) {
					return nan ? '' : value;
				}
				return parseFloat(value).toFixed(this.decimalPrecision);
				// return
				// parseFloat(parseFloat(value).toFixed(this.decimalPrecision));
			}
		});

// fix bug for display when format is Ym
Ext
		.apply(
				Date,
				{
					createParser : function(format) {
						var funcName = "parse" + Date.parseFunctions.count++;
						var regexNum = Date.parseRegexes.length;
						var currentGroup = 1;
						Date.parseFunctions[format] = funcName;

						var code = "Date."
								+ funcName
								+ " = function(input){\n"
								+ "var y, m, d, h = 0, i = 0, s = 0, ms = 0, o, z, u, v;\n"
								+ "input = String(input);\n"
								+ "d = getServerTime();\n"
								+ "y = d.getFullYear();\n"
								+ "m = d.getMonth();\n"
								// used to be d = d.getDate()
								+ "d = 1;\n"
								+ "var results = input.match(Date.parseRegexes["
								+ regexNum + "]);\n"
								+ "if (results && results.length > 0) {";
						var regex = "";

						var special = false;
						var ch = '';
						for (var i = 0; i < format.length; ++i) {
							ch = format.charAt(i);
							if (!special && ch == "\\") {
								special = true;
							} else if (special) {
								special = false;
								regex += String.escape(ch);
							} else {
								var obj = Date.formatCodeToRegex(ch,
										currentGroup);
								currentGroup += obj.g;
								regex += obj.s;
								if (obj.g && obj.c) {
									code += obj.c;
								}
							}
						}

						code += "if (u){\n"
								+ "v = new Date(u * 1000);\n"
								+ "}else if (y >= 0 && m >= 0 && d > 0 && h >= 0 && i >= 0 && s >= 0 && ms >= 0){\n"
								+ "v = new Date(y, m, d, h, i, s, ms);\n"
								+ "}else if (y >= 0 && m >= 0 && d > 0 && h >= 0 && i >= 0 && s >= 0){\n"
								+ "v = new Date(y, m, d, h, i, s);\n"
								+ "}else if (y >= 0 && m >= 0 && d > 0 && h >= 0 && i >= 0){\n"
								+ "v = new Date(y, m, d, h, i);\n"
								+ "}else if (y >= 0 && m >= 0 && d > 0 && h >= 0){\n"
								+ "v = new Date(y, m, d, h);\n"
								+ "}else if (y >= 0 && m >= 0 && d > 0){\n"
								+ "v = new Date(y, m, d);\n"
								+ "}else if (y >= 0 && m >= 0){\n"
								+ "v = new Date(y, m);\n"
								+ "}else if (y >= 0){\n"
								+ "v = new Date(y);\n"
								+ "}\n}\nreturn (v && (z || o))?"
								+ " (Ext.type(z) == 'number' ? v.add(Date.SECOND, -v.getTimezoneOffset() * 60 - z) :"
								+ " v.add(Date.MINUTE, -v.getTimezoneOffset() + (sn == '+'? -1 : 1) * (hr * 60 + mn))) : v;\n"
								+ "}";

						Date.parseRegexes[regexNum] = new RegExp("^" + regex
								+ "$", "i");
						eval(code);
					}
				});

/*******************************************************************************
 * 表单工具方法
 ******************************************************************************/

/**
 * 表单提交
 * 
 * @class Wonders.utils.formSubmit
 * 
 * @param button
 *            提交按钮对象（可通过Wonders.getCmp('按钮id')获得）
 * @param formId
 *            表单id
 * @param successFunction
 *            提交成功后的操作
 * @param successMsg
 *            提交成功后的提示信息
 * @param errorFunction
 *            提交失败后的操作
 * @param errorMsg
 *            提交失败后的提示信息
 * @param urlParams
 *            加载额外参数
 * @param buttonDisabled
 *            提交后按钮是否禁用（默认为true）
 */
Wonders.utils.formSubmit = function(button, formId, successFunction,
		successMsg, errorFunction, errorMsg, urlParams, buttonDisabled) {

	button.disable();

	if (typeof (buttonDisabled) == 'undefined') {
		buttonDisabled = true;
	}
	if (typeof (urlParams) == 'undefined') {
		urlParams = {};
	}
	if (typeof (__GUID__) != 'undefined') {
		urlParams._GUID_ = __GUID__;
	}
	var formCmp = Ext.getCmp(formId);
	if (formCmp.url == null || formCmp.url == '') {
		Wonders.Msg
				.error('\u8bf7\u5728form\u6807\u7b7e\u4e0a\u8bbe\u7f6eUrl\u5c5e\u6027\uff01');
		return;
	}
	var form = formCmp.form;

	// 处理combobox value/rawValue问题
	var combos = formCmp.findByType('combo');
	for (var i = 0; i < combos.length; i++) {
		if (combos[i].editable) {
			var cb = combos[i], st = cb.store;
			var val = cb.getValue(), rawVal = cb.getRawValue();
			// 处理场景：js代码调用setValue方式设值
			if (cb.selectedIndex == undefined) {
				val ? true : cb.setValue(rawVal);
			} else {
				// 处理场景：手动输入值，后台过滤后无数据
				if (cb.selectedIndex == -1) {
					cb.setValue(rawVal);
					// 特殊场景：输入值竟然存在store匹配项，则传递record
					st.each(function(r) {
						if (r.get(cb.displayField) == rawVal) {
							cb.setValue(r.get(cb.valueField));
							return;
						}
					});
				}
			}
		}
	}

	if (Wonders.utils.validateForm(formId)) {

		// 修复提交时，emptyText也一起提交的问题
		var fd = null;
		var submitValues = form.getValues();
		for ( var param in submitValues) {
			fd = form.findField(param);
			if (fd && fd.emptyText == submitValues[param]) {
				if (form.standardSubmit) {// 同步提交,不能使用'',必须' ',长度1
					fd.setValue(' ');
				} else {
					fd.setValue('');
				}
			}
		}

		if (form.standardSubmit) {
			form.submit();
		} else {
			form
					.doAction(
							'submit',
							{
								url : formCmp.url,
								waitMsg : (typeof (formCmp.waitMsg) != undefined) ? formCmp.waitMsg
										: '\u63d0\u4ea4\u4e2d...',
								params : (typeof (formCmp.baseParams) != 'undefined') ? formCmp.baseParams
										: urlParams,
								method : (typeof (formCmp.method) != 'undefined') ? formCmp.method
										: 'post',
								success : function(form, action) {
									if (successFunction) {
										if (successFunction(form, action) != false) {
											if (successMsg) {
												Wonders.Msg.info(successMsg);
											} else {
												Wonders.Msg
														.info('\u63d0\u4ea4\u6210\u529f!');
											}
										}
									} else {
										if (successMsg) {
											Wonders.Msg.info(successMsg);
										} else {
											Wonders.Msg
													.info('\u63d0\u4ea4\u6210\u529f!');
										}
									}
									if (!buttonDisabled) {
										button.enable();
									}
								},
								failure : function(form, action) {
									if (errorFunction) {
										if (errorFunction(form, action) != false) {
											if (errorMsg) {
												Wonders.Msg.info(errorMsg);
											} else {
												Wonders.utils
														.handleError(
																action.response.responseText,
																false, false);
											}
										}
									} else {
										if (typeof (__WSSIP_FAILURE_HANLDER__) == 'function') {
											__WSSIP_FAILURE_HANLDER__(form,
													action);
										} else if (errorMsg) {
											Wonders.Msg.info(errorMsg);
										} else {
											Wonders.utils
													.handleError(
															action.response.responseText,
															false, false);
										}
									}
									button.enable();
								}
							})
		}
	} else {
		button.enable();
	}
}
Wonders.form.submit = Wonders.utils.formSubmit;

/**
 * 验证表单辅助方法
 * 
 * @ignore
 */
Wonders.utils.error_html = null;

/**
 * 验证表单输入字段，支持嵌套表单
 * 
 * @class Wonders.utils.validateForm
 * @param formId
 *            表单ID
 */
Wonders.utils.validateForm = function(formId) {
	var form = Ext.getCmp(formId);
	var errorText = "";
	var firstErrorItem;
	if (form.items) {
		for (var i = 0; i < form.items.length; i++) {
			var item = form.items.get(i);
			// \u5047\u5982\u662f\u5bb9\u5668
			if (item.getXTypes().indexOf("field") > -1 && !item.validate()) {
				if (form.getXType() == 'htmlform'
						&& (form.getErrorStyle() == 'allalert' || form
								.getErrorStyle() == 'print')) {
					errorText += '[' + item.fieldLabel + ']: '
							+ item.invalidText + '<br>';
					if (firstErrorItem == null) {
						firstErrorItem = item;
					}
				} else {
					Wonders.Msg.info('[' + item.fieldLabel + ']: '
							+ item.invalidText, '提示', function() {
						item.focus();
					});
					return false;
				}
			}
		}
	}
	if (errorText != '') {
		if (form.getXType() == 'htmlform' && form.getErrorStyle() == 'allalert') {
			firstErrorItem.focus();
			Wonders.Msg.info(errorText);
		} else if (form.getXType() == 'htmlform'
				&& form.getErrorStyle() == 'print') {
			if (Wonders.utils.error_html != null)
				Wonders.utils.error_html.remove();
			Wonders.utils.error_html = form.body.insertHtml('afterBegin',
					'<font color=red>' + errorText + '</font>', true);
			form.body.insertHtml('afterBegin',
					'<a href="#" id="printMode"><a>', true);
			document.getElementById('printMode').click();
		}
		return false;
	} else {
		if (form.getXType() == 'htmlform' && form.getErrorStyle() == 'print') {
			if (Wonders.utils.error_html != null)
				Wonders.utils.error_html.remove();
		}
	}
	return true;
}

Wonders.form.validate = Wonders.utils.validateForm;

/**
 * 表单加载数据
 * 
 * @class Wonders.utils.formLoad
 * 
 * @param formId
 *            表单ID
 * @param url
 *            加载url
 * @param urlParams
 *            加载额外参数
 * @param successFunction
 *            加载成功后的操作
 * @param successMsg
 *            加载成功后的提示信息
 * @param errorFunction
 *            加载失败后的操作
 * @param errorMsg
 *            加载失败后的提示信息
 * @param waitMsg
 *            等待信息
 * @param waitTitle
 *            等待标题
 */
Wonders.utils.formLoad = function(formId, url, urlParams, successFunction,
		successMsg, errorFunction, errorMsg, waitMsg, waitTitle) {
	// 扩展Ext.data.JsonReader，表格数据加载的时候，捕获异常消息
	Ext.apply(Ext.data.JsonReader.prototype, {
		read : function(response) {
			var json = response.responseText;
			var o = eval("(" + json + ")");
			if (!o) {
				throw {
					message : "JsonReader.read: Json object not found"
				};
			}

			if (o.metaData) {
				delete this.ef;
				this.meta = o.metaData;
				this.recordType = Ext.data.Record.create(o.metaData.fields);
				this.onMetaChange(this.meta, this.recordType, o);
			}

			return this.readRecords(o);
		}
	});

	var formCmp = Ext.getCmp(formId);
	formCmp
			.load({
				url : url,
				params : (typeof (urlParams) != 'undefined') ? urlParams : {},
				waitMsg : (typeof (waitMsg) != 'undefined' && waitMsg != '') ? waitMsg
						: '\u6b63\u5728\u52a0\u8f7d\u6570\u636e...',
				waitTitle : (typeof (waitTitle) != 'undefined' && waitTitle != '') ? waitTitle
						: '\u8bf7\u7a0d\u540e...',
				success : function(form, action) {
					var fieldNames = action.result.data;
					var linkage = [];
					for ( var fieldName in fieldNames) {
						if (form.findField(fieldName) != null) {
							var field = form.findField(fieldName);

							for ( var attribute in Wonders.utils.atrLinkResponse) {
								if (attribute == fieldName
										&& Wonders.utils.atrLinkResponse[attribute] != undefined
										&& Wonders.utils.atrLinkResponse[attribute] != '') {
									field
											.setValue(Wonders.utils.atrLinkResponse[attribute]);
								}
							}

							if (field.getXType() == 'combo') {
								if (field.parentField == null) {
									if (field.mode == 'local') { // \u672c\u5730\u52a0\u8f7d\u6570\u636e\u7684combobox
										;
									} else if (field.tpl == undefined) { // \u666e\u901a\u4e0b\u62c9\u6846
										// \u521d\u59cb\u5316\u4e0b\u62c9\u6846
										Wonders.Combo.loadCombobox(form,
												fieldName);
									} else { // \u4e0b\u62c9\u8868\u683c
										// \u53c2\u6570\u5206\u522b\u4e3aform,action,
										// valueField(\u503c\u57df),
										// textField(\u663e\u793a\u57df)
										Wonders.Combo.loadGridSelect(form,
												action, fieldName,
												field.displayField);
									}
								} else { // \u6b64\u4e3a\u8054\u52a8\u4e0b\u62c9\u6846\u60c5\u51b5
									var parentProperty = form
											.findField(field.parentField).hiddenName;
									// if (!IsContain(linkage,parentProperty)){
									linkage.push(parentProperty);
									// }
									linkage.push(fieldName);
								}
							} else if (field.getXType() == 'treeField') {
								Wonders.Combo.loadTreeSelect(form, action,
										fieldName);
							}
						}
					}

					if (linkage.length > 0) {
						for (var i = 0; i < linkage.length; i++) {
							if (i % 2 == 1) {
								if (linkage[i] == linkage[i + 1]
										|| linkage[i - 1] == linkage[i + 1]) {
									// \u521d\u59cb\u5316\u8054\u52a8\u6846,\u53c2\u6570\u4ece\u6700\u4e0a\u5c42\u5f00\u59cb(\u6700\u591a\u652f\u6301\u4e09\u7ea7)
									Wonders.Combo.loadLinkage(form,
											linkage[i - 1], linkage[i],
											linkage[i + 2]);
									i = i + 2;
								} else {
									Wonders.Combo.loadLinkage(form,
											linkage[i - 1], linkage[i]);
								}
							}
						}
					}

					if (successFunction) {
						if (successFunction(form, action) != false) {
							if (successMsg) {
								Wonders.Msg.info(successMsg);
							} else {
								// Wonders.Msg.info('\u52a0\u8f7d\u6210\u529f!');
							}
						}
					} else {
						if (successMsg) {
							Wonders.Msg.info(successMsg);
						} else {
							// Wonders.Msg.info('\u52a0\u8f7d\u6210\u529f!');
						}
					}
				},
				failure : function(form, action) {
					if (errorFunction) {
						if (errorFunction(form, action) != false) {
							if (errorMsg) {
								Wonders.Msg.info(errorMsg);
							} else {
								Wonders.utils.handleError(
										action.response.responseText, false,
										false);
							}
						}
					} else {
						if (errorMsg) {
							Wonders.Msg.info(errorMsg);
						} else {
							Wonders.utils.handleError(
									action.response.responseText, false, false);
						}
					}
				}
			});
}

Wonders.form.load = Wonders.utils.formLoad;

// private
/**
 * @ignore 前台数据表单加载
 * @class Wonders.utils.initFormLoad
 * @param form
 *            表单对象
 * @param fieldNames
 *            表单所有元素的name集合 为数组
 */
Wonders.utils.initFormLoad = function(form, fieldNames) {
	var linkage = [];
	for (var i = 0; i < fieldNames.length; i++) {
		fieldName = fieldNames[i];
		if (form.form.findField(fieldName) != null) {
			var field = form.form.findField(fieldName);
			if (field.getXType() == 'combo' && field.parentField != null) { // \u6b64\u4e3a\u8054\u52a8\u4e0b\u62c9\u6846\u60c5\u51b5
				var parentProperty = form.form.findField(field.parentField).hiddenName;
				linkage.push(parentProperty);
				linkage.push(fieldName);
			}
		}
	}

	if (linkage.length > 0) {
		for (var i = 0; i < linkage.length - 1; i++) {
			if (i % 2 == 1) {
				if (linkage[i] == linkage[i + 1]
						|| linkage[i - 1] == linkage[i + 1]) {
					// \u521d\u59cb\u5316\u8054\u52a8\u6846,\u53c2\u6570\u4ece\u6700\u4e0a\u5c42\u5f00\u59cb(\u6700\u591a\u652f\u6301\u4e09\u7ea7)
					Wonders.Combo.loadLinkage(form.form, linkage[i - 1],
							linkage[i], linkage[i + 2]);
					i = i + 2;
				} else {
					Wonders.Combo.loadLinkage(form.form, linkage[i - 1],
							linkage[i]);
				}
			}
		}
	}
}
Wonders.form.initLoad = Wonders.utils.initFormLoad;

/**
 * 增加表格表单一起提交支持
 * 
 * @class Wonders.form.submitIncludeGrid
 * 
 * @param button
 *            提交按钮对象（可通过Wonders.getCmp('按钮id')获得）
 * @param formId
 *            表单id
 * @param gridArray
 *            表格对象列表
 * @param successFunction
 *            提交成功后的操作
 * @param successMsg
 *            提交成功后的提示信息
 * @param errorFunction
 *            提交失败后的操作
 * @param errorMsg
 *            提交失败后的提示信息
 * @param buttonDisabled
 *            提交后按钮是否禁用（默认为true）
 */
Wonders.form.submitIncludeGrid = function(button, formId, gridArray,
		successFunction, successMsg, errorFunction, errorMsg, buttonDisabled) {

	button.disable();
	var formCmp = Ext.getCmp(formId);

	var params = {};
	if (gridArray instanceof Array) {
		for (var i = 0; i < gridArray.length; ++i) {
			var grid = gridArray[i];
			var json = Wonders.grid.createJsonData(grid);

			var jsonData = json[0];
			var jsonDataOfDel = json[1];

			params = Wonders.grid.createParams(grid.property + "modifiedData",
					jsonData, params);
			params = Wonders.grid.createParams(grid.property + "deleteData",
					jsonDataOfDel, params);
		}
	}

	if (Wonders.utils.validateForm(formId)) {
		formCmp.form
				.doAction(
						'submit',
						{
							url : formCmp.url,
							waitMsg : (typeof (formCmp.waitMsg) != undefined) ? formCmp.waitMsg
									: '\u63d0\u4ea4\u4e2d...',
							params : (typeof (params) != 'undefined') ? params
									: {},
							method : (typeof (formCmp.method) != 'undefined') ? formCmp.method
									: 'post',
							success : function(form, action) {
								if (successFunction) {
									if (successFunction(form, action) != false) {
										if (typeof (successMsg) != 'undefined') {
											Wonders.Msg.info(successMsg);
										} else {
											Wonders.Msg
													.info('\u63d0\u4ea4\u6210\u529f!');
										}
									}
								} else {
									if (typeof (successMsg) != 'undefined') {
										Wonders.Msg.info(successMsg);
									} else {
										Wonders.Msg
												.info('\u63d0\u4ea4\u6210\u529f!');
									}
								}

								// \u589e\u52a0grid store
								// commit,\u5bf9\u591a\u4e2agrid\u6839\u636egrid\u7684id\u8fdb\u884c\u6570\u636ereload
								if (gridArray instanceof Array) {
									var result = Ext
											.decode(action.response.responseText);
									for (var i = 0; i < gridArray.length; ++i) {
										var grid = gridArray[i];
										Wonders.grid.reloadGrid(grid, true,
												result);
									}
								}
								if (!buttonDisabled) {
									button.enable();
								}
							},
							failure : function(form, action) {
								if (errorFunction) {
									if (errorFunction(form, action) != false) {
										if (errorMsg) {
											Wonders.Msg.info(errorMsg);
										} else {
											Wonders.utils
													.handleError(
															action.response.responseText,
															false, false);
										}
									}
								} else {
									if (errorMsg) {
										Wonders.Msg.info(errorMsg);
									} else {
										Wonders.utils.handleError(
												action.response.responseText,
												false, false);
									}
								}
								button.enable();
							}
						});
	} else {
		button.enable();
	}
}

/**
 * 统一提交入口，根据form中的gridArray来进行实际调用分发
 * 
 * @class Wonders.form.unityFormSubmit
 * 
 * @param button
 *            提交按钮对象（可通过Wonders.getCmp('按钮id')获得）
 * @param formId
 *            表单id
 * @param successFunction
 *            提交成功后的操作
 * @param successMsg
 *            提交成功后的提示信息
 * @param errorFunction
 *            提交失败后的操作
 * @param errorMsg
 *            提交失败后的提示信息
 * @param buttonDisabled
 *            提交后按钮是否禁用（默认为true）
 */
Wonders.form.unityFormSubmit = function(button, formId, successFunction,
		successMsg, errorFunction, errorMsg, buttonDisabled) {

	var formCmp = Ext.getCmp(formId);

	if (formCmp.url == null || formCmp.url == '') {
		Wonders.Msg
				.error('\u8bf7\u5728form\u6807\u7b7e\u4e0a\u8bbe\u7f6eUrl\u5c5e\u6027\uff01');
		return;
	}

	var gridArray = formCmp.getGridArray();

	// button.disable();

	if ((typeof (gridArray) == 'undefined') || gridArray.length == 0) {
		Wonders.utils.formSubmit(button, formId, successFunction, successMsg,
				errorFunction, errorMsg, buttonDisabled);
	} else {
		Wonders.form.submitIncludeGrid(button, formId, gridArray,
				successFunction, successMsg, errorFunction, errorMsg,
				buttonDisabled);
	}
}

/**
 * @ignore
 */
randomChar = function(length) {
	var chars = "0123456789";
	var result = "";
	for (var i = 0; i < length; i++) {
		result += chars.charAt(Math.ceil(Math.random() * 100000000)
				% chars.length);
	}
	return result;
}

/**
 * @ignore
 */
Wonders.form.addFile = function(id, random) {
	var isIE = Ext.isIE;
	var div = document.getElementById(id + "_div");
	var allowFileType = div.getAttribute("allowFileType");
	var fileSize = div.getAttribute("fileSize");
	var fileCount = div.getAttribute("fileCount");
	var buttonImg = div.getAttribute("buttonImg");
	var removeImg = div.getAttribute("removeImg");

	var fileId = id + "_" + random;
	var file = Ext.get(fileId);
	var filename = file.dom.value;
	var nameAttr = file.dom.name;
	if (filename == '') {
		return;
	}

	// 校验上传文件类型:fileType
	if (allowFileType && allowFileType.length > 0) {
		var aft = allowFileType.replace(new RegExp(" ", "gm"), "");// 替换空格
		aft = aft.replace(new RegExp("\\u002A", "gm"), "\\");// 替换*号
		aft = aft.replace(new RegExp(";", "gm"), "|");// 替换;号
		aft = "(.*)(" + aft + ")$";
		aft = new RegExp(aft);
		if (aft.test(filename) == false) {
			if (isIE) {// IE
				var newDom = file.dom.cloneNode(false);
				newDom.onchange = file.dom.onchange;// events are not cloned
				file.dom.parentNode.replaceChild(newDom, file.dom);
			} else {// FF
				file.dom.value = "";
			}
			return;
		}
	}
	// 校验上传文件大小:fileSize
	if (fileSize > 0) {
		var size = 0;
		if (isIE && !file.dom.files) {
			var flag = false;
			try {
				var fileSystem = new ActiveXObject("Scripting.FileSystemObject");
				size = fileSystem.GetFile(file.dom.value).size;
				size /= 1024 * 1024;
				if (size > fileSize) {
					flag = true;
					Wonders.Msg
							.info("\u8bf7\u786e\u8ba4\u4e0a\u4f20\u6587\u4ef6\u5c0f\u4e8e"
									+ fileSize + "M!");
				}
			} catch (ect) {
				flag = true;
				Wonders.Msg
						.info("\u8bf7\u786e\u8ba4\u6d4f\u89c8\u5668\u5b89\u5168\u8bbe\u7f6e:\u5bf9\u6ca1\u6709\u6807\u8bb0\u4e3a\u5b89\u5168\u7684ActiveX\u63a7\u4ef6\u8fdb\u884c\u521d\u59cb\u5316\u548c\u811a\u672c\u8fd0\u884c  \u5df2\u542f\u7528!");
			}
			if (flag) {
				var newDom = file.dom.cloneNode(false);
				newDom.onchange = file.dom.onchange;// events are not cloned
				file.dom.parentNode.replaceChild(newDom, file.dom);
				return;
			}
		} else {
			size = file.dom.files[0].size;
			size /= 1024 * 1024;
			if (size > fileSize) {
				file.dom.value = "";
				Wonders.Msg
						.info("\u8bf7\u786e\u8ba4\u4e0a\u4f20\u6587\u4ef6\u5c0f\u4e8e"
								+ fileSize + "M!");
				return;
			}
		}
	}

	var wrapDiv = file.parent();
	var outerDiv = wrapDiv.parent();
	// 校验上传文件数量:fileCount
	if (fileCount > 0) {
		var count = 0;
		var inputs = outerDiv.dom.getElementsByTagName("input");
		var index = inputs.length;
		while (index--) {
			if (inputs[index].getAttribute("name") == nameAttr) {
				count++;
			}
		}
		if (count == fileCount) {
			return;
		}
	}

	var newRandom = randomChar(6);
	var newFieldId = id + "_" + newRandom;

	var newFieldDom = file.dom.cloneNode(false);
	newFieldDom.id = newFieldId;
	if (isIE) {
		newFieldDom.onchange = function() {
			Wonders.form.addFile(id, newRandom)
		};
	} else {
		newFieldDom.addEventListener('change', function() {
			Wonders.form.addFile(id, newRandom)
		}, false);
		newFieldDom.value = "";
	}

	var newWrapDom = wrapDiv.dom.cloneNode(false);
	newWrapDom.id = newFieldId + "_div";
	newWrapDom.appendChild(newFieldDom);

	outerDiv.dom.insertBefore(newWrapDom, wrapDiv.dom);

	var deleteField = "<input id='"
			+ fileId
			+ "_btn' type='button' value='\u5220\u9664' class='x-btn-text' onclick='Wonders.form.deleteFile(\""
			+ fileId + "\")'>";
	wrapDiv.insertHtml('beforeEnd', deleteField);

	// 上方对齐
	var df = Ext.get(fileId + "_btn");
	var y = file.getY();
	if (df.getY() != y) {
		df.setY(y);
	}
}
/**
 * @ignore
 */
Wonders.form.deleteFile = function(fileId) {
	var div = Ext.get(fileId).dom.parentNode;
	div.parentNode.removeChild(div);
}

/**
 * 用于手动加载下拉框控件
 * 
 * @class Wonders.Combo.loadCombobox
 * @param form
 *            表单id
 * @param comboName
 *            combobox的id或name
 * 
 * author Wangkehao
 */
Wonders.Combo.loadCombobox = function(form, comboName) {
	if (typeof (form) == 'string') {
		form = Ext.getCmp(form).getForm();
	}

	var combo = form.findField(comboName);
	combo.store.on('load', function(store, records) {
		combo.setValue(combo.getValue());
	});
	combo.store.load();
},

/**
 * 用于手动加载联动控件
 * 
 * @class Wonders.Combo.loadLinkage
 * @param form
 *            表单id
 * @param comboName
 *            最上层combobox的id或name
 * @param comboName1
 *            第二层combobox的id或name
 * @param comboName2
 *            第三层combobox的id或name
 */
Wonders.Combo.loadLinkage = function(form, comboName, comboName1, comboName2) {
	if (typeof (form) == 'string') {
		form = Ext.getCmp(form).getForm();
	}

	var loadFlag = true;
	var combo, combo1, combo2;
	combo = form.findField(comboName);
	if (comboName2 != undefined) {
		combo1 = form.findField(comboName1);
		combo2 = form.findField(comboName2);
	} else {
		combo1 = form.findField(comboName2);
		combo2 = form.findField(comboName1);
	}

	var value = combo.getValue();
	var value1 = combo1.getValue();
	var value2 = combo2.getValue();

	// \u7b2c\u4e00\u7ea7
	combo.store.on('load', function(store, records) {
		if (loadFlag) {
			combo.setValue(value);
			var valueField = combo.valueField;
			var i;
			var hasValue = false;
			for (i = 0; i < records.length; i++) {
				if (records[i].get(valueField) == value
						&& records[i].get(valueField) != '') {
					hasValue = true;
					break;
				}
			}
			if (!hasValue) {
				combo.setValue('');
				combo1.setValue('');
				combo2.setValue('');

				loadFlag = false;
			} else {
				combo.fireEvent('select', combo, records[i]);
			}
			if (comboName2 != undefined) {
				combo1.store.load();
			} else {
				combo2.store.load();
			}
		}
	});
	//

	// \u7b2c\u4e8c\u7ea7
	if (comboName2 != undefined) {
		combo1.store.on('load', function(store, records) {
			if (loadFlag) {
				combo1.setValue(value1);
				combo1.setDisabled(false);

				var valueField = combo1.valueField;
				var i;
				var hasValue = false;
				for (i = 0; i < records.length; i++) {
					if (records[i].get(valueField) == value1
							&& records[i].get(valueField) != '') {
						hasValue = true;
						break;
					}
				}

				if (!hasValue) {
					combo1.setValue('');

					if (combo1.parentField != combo2.parentField) {
						loadFlag = false;
					}
				} else {
					combo1.fireEvent('select', combo1, records[i]);
				}
				combo2.store.load();
			}
		});
	}
	//

	// \u7b2c\u4e09\u7ea7
	combo2.store.on('load', function(store, records) {
		if (loadFlag) {
			combo2.setDisabled(false);
			combo2.setValue(value2);

			var valueField = combo2.valueField;
			var i;
			var hasValue = false;
			for (i = 0; i < records.length; i++) {
				if (records[i].get(valueField) == value2
						&& records[i].get(valueField) != '') {
					hasValue = true;
					break;
				}
			}

			if (!hasValue) {
				combo2.setValue('');
			}
			loadFlag = false;
		}
	});
	// 

	combo.store.load();
},

/**
 * @ignore
 */
Wonders.Combo.loadTreeSelect = function(form, action, valueField) {
	var treeSelect = form.findField(valueField);
	for ( var p in action.result.data) {
		if (p == valueField) {
			if (action.result.data[p].value == "") {
				treeSelect.hiddenField.setValue(" ");
				treeSelect.setValue(" ");
			}
			if (action.result.data[p].value && action.result.data[p].text) {
				treeSelect.hiddenField.setValue(action.result.data[p].value);
				treeSelect.setValue(action.result.data[p].text);
				break;
			}
		}
	}
	treeSelect.hasFocus = true;
	treeSelect.menu.show(treeSelect.el, 'tl-bl');
	treeSelect.menu.hide();
},

/**
 * @ignore
 */
Wonders.Combo.loadGridSelect = function(form, action, valueField, textField) {
	var combo = form.findField(valueField);
	for ( var p in action.result.data) {
		if (p == textField) {
			combo.setRawValue(action.result.data[p]);
			break;
		}
	}
}

/**
 * @ignore 得到store的field值,json格式
 */
Wonders.Combo.getFieldsJson = function(combo, value, text) {
	var store_fields = combo.store.fields;
	var fieldsJson = '{';
	for (i = 0; i < store_fields.length; i++) {
		if (combo.valueField == store_fields.get(i).name) {
			fieldsJson += store_fields.get(i).name + ':"' + value + '",';
		} else if (combo.displayField == store_fields.get(i).name) {
			fieldsJson += store_fields.get(i).name + ':"' + text + '",';
		} else {
			fieldsJson += store_fields.get(i).name + ':"",';
		}
	}
	fieldsJson = fieldsJson.substring(0, fieldsJson.length - 1) + '}';
	return fieldsJson;
}

/**
 * 用于手动查询下拉表格数据
 * 
 * @class Wonders.form.doQueryGridSelect
 * @param gridselect
 *            下拉表格组件id
 * @param q
 *            查询参数
 * @param completefunction
 *            查询成功之后的操作
 * @param selectAt
 *            查询成功之后选择记录的位置
 */
Wonders.form.doQueryGridSelect = function(gridselect, q, completefunction,
		selectAt) {
	var combo = Ext.getCmp(gridselect);
	if (!selectAt) {
		selectAt = 0;
	}
	var forceAll = true;
	if (q === undefined || q === null) {
		q = '';
	}
	var qe = {
		query : q,
		forceAll : forceAll,
		combo : combo,
		cancel : false
	};
	if (combo.fireEvent('beforequery', qe) === false || qe.cancel) {
		return false;
	}
	q = qe.query;
	forceAll = qe.forceAll;
	if (forceAll === true || (q.length >= this.minChars)) {
		if (combo.lastQuery !== q) {
			combo.lastQuery = q;
			if (combo.mode == 'local') {
				combo.selectedIndex = -1;
				if (forceAll) {
					combo.store.clearFilter();
				} else {
					combo.store.filter(combo.displayField, q);
				}
				combo.onLoad();
			} else {
				combo.store.baseParams[combo.queryParam] = q;
				combo.store
						.load({
							params : combo.getParams(q),
							callback : function(record, o, success) {
								if (success) {
									if (!record[selectAt]) {
										Wonders.Msg
												.info('\u8bb0\u5f55\u4e0d\u5b58\u5728\uff0c\u65e0\u6cd5\u81ea\u52a8\u9009\u62e9\uff01');
										return;
									}
									if (completefunction) {
										combo
												.setValue(record[selectAt].data[combo.valueField
														|| combo.displayField]);
										completefunction(record);
									} else {
										combo
												.setValue(record[selectAt].data[combo.valueField
														|| combo.displayField]);
									}
								}
							}
						});
				combo.expand();
			}
		} else {
			combo.selectedIndex = -1;
			combo.onLoad();
		}
	}
}

Wonders.utils.atrLinkResponse;

/**
 * 联动数据加载
 * 
 * @class Wonders.utils.formLoadLinkage
 * @param linkageUrl
 *            加载联动数据url
 * @param linkageUrlParams
 *            加载联动数据额外参数
 * @param formId
 *            表单ID
 * @param url
 *            加载url
 * @param urlParams
 *            加载额外参数
 * @param successFunction
 *            加载成功后的操作
 * @param successMsg
 *            加载成功后的提示信息
 * @param errorFunction
 *            加载失败后的操作
 * @param errorMsg
 *            加载失败后的提示信息
 * @param waitMsg
 *            等待信息
 * @param waitTitle
 *            等待标题
 */
Wonders.utils.formLoadLinkage = function(linkageUrl, linkageUrlParams, formId,
		url, urlParams, successFunction, successMsg, errorFunction, errorMsg,
		waitMsg, waitTitle) {
	Wonders.utils.request(linkageUrl, linkageUrlParams, 'POST', function(
			response, options) {
		Wonders.utils.atrLinkResponse = Ext.decode(response.responseText);
		Wonders.utils.formLoad(formId, url, urlParams, successFunction,
				successMsg, errorFunction, errorMsg, waitMsg, waitTitle);
	});
}

// 以下代码,修正直接使用linkage若干问题,可通过combobox模拟实现
// 此处模拟一次调用监听器
// 注意下面函数调用方式,第三个参数scope必须是控件本身
// 同样此种setValue方式可应用到独立的combobox控件
Wonders.Combo.onceValueListener = function(store, records, options) {
	// 通过自定义属性设值
	this.setValue(this.defaultValue);

	var index = store.find(this.valueField, this.defaultValue);
	var record = store.getAt(index);

	// 删除自定义额外属性
	delete this.defaultValue;

	// 远程数据请求则删除监听器本身
	store.un("load", Wonders.Combo.onceValueListener, this);

	// 必须触发select事件,通知下级加载数据
	// 但注意一个副作用,如果用户注册了select监听器,
	// 此时触发有可能不是用户希望的手动选择触发,可通过-1判断隔离
	this.fireEvent('select', this, record, -1);
}

// 执行下拉框的设值
// 同时可以应用于联动下拉的最顶层
// 因为按照目前的设计来讲,联动下拉下级只能通过url配置数据,而顶层可以是本地数据
Wonders.Combo.setValue = function(combobox, value) {
	typeof (combobox) == "string" ? combobox = Ext.getCmp(combobox) : null;
	value ? combobox.defaultValue = value : null;

	var store = combobox.store;
	if (store.getCount() > 0) {
		value = combobox.defaultValue;
		delete combobox.defaultValue;
		combobox.setValue(value);
		var chs = combobox.childrenField;
		var index = store.find(combobox.valueField, value);
		chs && chs.length ? combobox.fireEvent('select', combobox,
				index != -1 ? store.getAt(index) : null, -1) : false;
	} else {
		store.on("load", Wonders.Combo.onceValueListener, combobox);
		combobox.doQuery("", true);
	}
}

// 此函数模拟formLoad时赋值
// 参数为最顶层linkage
// 如何判断是否为顶层联动下拉 ? -> parentField
Wonders.Combo.setLinkageValues = function(topLinkage, values) {
	// 初始化
	var doSetValue = function(linkage, values) {
		var chs = linkage.childrenField;
		var l = chs ? chs.length : 0;
		var v = "";
		var st = null;
		while (l--) {
			v = values[chs[l].name];
			if (v != undefined && v != "") {
				chs[l].defaultValue = v;
				st = chs[l].store;
				if (st.proxy.activeRequest) {
					Ext.Ajax.abort(st.proxy.activeRequest);
				}
				st.on("load", Wonders.Combo.onceValueListener, chs[l]);
			}
			doSetValue(chs[l], values);
		}
	}

	typeof (topLinkage) == "string" ? topLinkage = Ext.getCmp(topLinkage)
			: null;
	topLinkage.defaultValue = values[topLinkage.name];
	doSetValue(topLinkage, values);

	var proxy = topLinkage.store.proxy;
	if (proxy.activeRequest) {
		Ext.Ajax.abort(proxy.activeRequest);
	}

	Wonders.Combo.setValue(topLinkage, topLinkage.defaultValue);
}

Wonders.Combo.registerLinkage = function(linkage, parentField, value) {
	typeof (linkage) == "string" ? linkage = Ext.getCmp(linkage) : false;

	var store = linkage.store;

	store.on("load", function() {
		Wonders.Combo.onLinkageLoad(linkage);
	});

	linkage.on("select", function(com, rec, index) {
		Wonders.Combo.onLinkageSelect(com, rec, index);
	});

	if (parentField) {
		// 属于下级联动下拉
		linkage.setDisabled(true);
		typeof (parentField) == "string" ? parentField = Ext
				.getCmp(parentField) : null;
		parentField.childrenField = parentField.childrenField || [];
		parentField.childrenField.push(linkage);
		if (value != false && value != null) {
			linkage.defaultValue = value;
			store.on("load", Wonders.Combo.onceValueListener, linkage);
		}
	}
}

// 高层进行加载数据时
// 清空间接下级数据并禁用
// 供私有调用
Wonders.Combo.onLinkageLoad = function(linkage) {
	typeof (linkage) == "string" ? linkage = Ext.getCmp(linkage) : false;
	var callback = function(children) {
		children = children || [];
		var l = children.length;
		var ch = null;
		while (l--) {
			ch = children[l];
			ch.clearValue();
			ch.setDisabled(true);
			callback(ch.childrenField);
		}
	}
	callback(linkage.childrenField);
}

// 当前联动框选择时,加载直接下级数据
// 供私有调用
Wonders.Combo.onLinkageSelect = function(linkage, record, index) {
	typeof (linkage) == "string" ? linkage = Ext.getCmp(linkage) : false;
	var children = linkage.childrenField;
	var l = children ? children.length : 0;
	var value = linkage.getValue();
	var ch = null;
	var st = null;
	while (l--) {
		ch = children[l];
		ch.setDisabled(false);
		ch.clearValue();
		st = ch.store;
		st.baseParams.parentValue = value;
		st.baseParams.parentId = record ? record.get("id") : "";
		ch.doQuery(value, true);
		// 加上此句,防止多次加载
		ch.lastQuery = "";
	}
}
// 设置combbox只读
Wonders.Combo.setReadOnly = function(combobox, readOnly) {
	typeof (combobox) == "string" ? combobox = Ext.getCmp(combobox) : false;
	var trigger = combobox.trigger;
	var wrap = combobox.wrap;
	var el = combobox.el;
	if (readOnly) {
		combobox.editable = true;
		trigger.setDisplayed(false);
		combobox.setEditable(false);
		el.setWidth(wrap.getWidth());
		combobox.on("beforequery", setTriggerDisable);
	} else {
		combobox.editable = false;
		trigger.setDisplayed(true);
		combobox.setEditable(true);
		el.setWidth(wrap.getWidth() - trigger.getWidth());
		combobox.un("beforequery", setTriggerDisable);
	}
}

/**
 * 手动设置下拉树的值
 * 
 * @class Wonders.Combo.setTreeSelectValue
 * @param field
 *            下拉树id/object
 * @param value
 *            设置的值
 * @param wide
 *            遍历算法,默认深度遍历,可配广度 注意单选树只针对第一个value设值 value对应的NODE必须存在
 * 
 */
Wonders.Combo.setTreeSelectValue = function(field, value, wide) {
	var treeselect = field;
	typeof (treeselect) == "string" ? treeselect = Ext.getCmp(field) : null;
	treeselect.setValue("");
	treeselect.hiddenField.setValue(value);

	var tree = treeselect.menu.picker.tree;
	if (!tree) {// 初始化树
		treeselect.onTriggerClick(treeselect, {
			preventDefault : true
		});
		treeselect.collapse();
		tree = treeselect.menu.picker.tree;
	}
	var rootNode = tree.getRootNode();
	var sm = tree.getSelectionModel();
	sm.clearSelections();

	var vArr = value.split(",");
	if (!sm.getSelectedNodes && vArr.length > 1) {// 单选树针对第一个而言
		vArr = [ vArr[0] ];
	}

	// 查找数组中某元素并删除之
	var indexOf = function(array, key) {
		var l = array.length;
		while (l--)
			if (array[l] == key) {
				array.splice(l, 1);
				return true;
			}

		return false;
	}
	// 保存树下拉文本结果
	var text = [];

	// 深度遍历
	var deepFun = function(root, node, sm, ts, display, valueArray) {
		if (indexOf(valueArray, node.id)) {// 当前节点包含值则选中
			var tx = node.text;
			sm.select(node, null, true);
			display.push(tx);
			ts.pathMap.add(node.getPath(), tx);
		}
		if (valueArray.length === 0) {// 以查找到所有值返回
			ts.setValue(display.join(","));
			display = null;
			valueArray = null;
			return;
		} else {
			if (!node.isLeaf()) {// 非叶子节点
				// ----------展开子节点操作-----------------
				node.expand(false, false, function() {
					var ch = node.childNodes;
					ch.length > 0 ? deepFun(root, ch[0], sm, ts, display,
							valueArray) : null;
				});
			} else {// 叶子节点直接返回
				var next = node.nextSibling;
				while (next == null && node != root) {
					node = node.parentNode;
					next = node.nextSibling;
				}
				if (next && next !== root) {
					deepFun(root, next, sm, ts, display, valueArray);
				}
				return;
			}
		}
	}

	var wideFun = function(node, sm, ts, display, valueArray) {
	}

	wide === true ? wideFun()/** 广度调用* */
	: deepFun(rootNode, rootNode, sm, treeselect, text, vArr)/** 深度调用* */
	;
}

/**
 * 自动设置下拉表格的第一行记录
 * 
 * @class Wonders.Combo.setTreeSelectValue
 * @param fieldId
 *            下拉表格id
 * @param valueField
 *            设置的值
 * 
 */
Wonders.Combo.setGridSelectFirstValue = function(fieldId, valueField) {
	var gridselect = Ext.getCmp(fieldId);
	// 设值
	gridselect.selectTask = new Ext.util.DelayedTask(function() {
		gridselect.onSelect(gridselect.store.getAt(0), 0);
	});
	gridselect.store.on('load', function(s, r, o) {
		if (r.length == 1) {
			gridselect.selectTask.delay(200);
		}
	});
}

Ext
		.apply(
				Ext.form.HtmlEditor.prototype,
				{
					enableImages : true,

					uploadUrl : '',

					dealURL : function(url, urlType) {
						var baseUrl = location, protocol = baseUrl.protocol, host = baseUrl.host, hostname = baseUrl.hostname, port = baseUrl.port, path = baseUrl.pathname
								.replace(/\\/g, '/').replace(/[^\/]+$/i, '');
						if (port === '')
							port = '80';
						if (path === '')
							path = '/';
						else if (path.charAt(0) !== '/')
							path = '/' + path;// 修正IE path
						url = url.trim();
						// 删除域路径
						var urlType = "rel";
						if (urlType !== 'abs')
							url = url.replace(new RegExp(protocol + '\\/\\/'
									+ hostname.replace(/\./g, '\\.') + '(?::'
									+ port + ')' + (port === '80' ? '?' : '')
									+ '(\/|$)', 'i'), '/');
						// 删除根路径
						if (urlType === 'rel')
							url = url.replace(new RegExp('^'
									+ path.replace(/([\/\.\+\[\]\(\)])/g,
											'\\$1'), 'i'), '');
						// 加上根路径
						if (urlType !== 'rel') {
							if (!url.match(/^(https?:\/\/|\/)/i))
								url = path + url;
							if (url.charAt(0) === '/')// 处理根路径中的..
							{
								var arrPath = [], arrFolder = url.split('/'), folder, i, l = arrFolder.length;
								for (i = 0; i < l; i++) {
									folder = arrFolder[i];
									if (folder === '..')
										arrPath.pop();
									else if (folder !== '' && folder !== '.')
										arrPath.push(folder);
								}
								if (arrFolder[l - 1] === '')
									arrPath.push('');
								url = '/' + arrPath.join('/');
							}
						}
						// 加上域路径
						if (urlType === 'abs' && !url.match(/^https?:\/\//i))
							url = protocol + '//' + host + url;
						url = url.replace(/(https?:\/\/[^:\/?#]+):80(\/|$)/i,
								'$1$2');// 省略80端口
						return url;
					},
					syncValue : function() {
						if (this.initialized) {
							var bd = this.getEditorBody();
							// 处理img的路径问题
							var imgs = bd.getElementsByTagName("img");
							var l = imgs.length;
							var img = null;
							var src = srcAttr = null;
							while (l--) {
								img = imgs[l];
								srcAttr = img.getAttribute("src");
								src = this.dealURL(srcAttr, "rel");
								src !== srcAttr ? img.setAttribute("src", src)
										: null;
							}

							// 处理超链接问题
							var _links = bd.getElementsByTagName("a");
							var _len = _links.length;
							var _link = null;
							while (_len--) {
								_link = _links[_len];
								_link.setAttribute("target", "_blank");
							}
							// --

							var html = bd.innerHTML;
							if (Ext.isSafari) {
								var bs = bd.getAttribute('style'); // Safari
																	// puts
																	// text-align
																	// styles on
																	// the body
																	// element!
								var m = bs.match(/text-align:(.*?);/i);
								if (m && m[1]) {
									html = '<div style="' + m[0] + '">' + html
											+ '</div>';
								}
							}
							html = this.cleanHtml(html);
							if (this.fireEvent('beforesync', this, html) !== false) {
								this.el.dom.value = html;
								this.fireEvent('sync', this, html);
							}
						}
					},

					createImage : function() {
						var editor = this;
						var imgform = new Ext.FormPanel(
								{
									region : 'center',
									labelWidth : 60,
									frame : true,
									bodyStyle : 'padding:5px 5px 0',
									autoScroll : true,
									border : false,
									fileUpload : true,
									items : [ {
										xtype : 'textfield',
										fieldLabel : '选择图片',
										name : 'fileData',
										inputType : 'file',
										allowBlank : false,
										blankText : '文件不能为空！',
										height : 22,
										anchor : '100%'
									} ],
									buttons : [
											{
												text : '上传',
												type : 'submit',
												handler : function() {
													if (!imgform.form.isValid()) {
														return;
													}
													imgform.form
															.submit({
																waitMsg : '正在上传',
																url : editor.uploadUrl,
																success : function(
																		form,
																		action) {
																	// var
																	// element =
																	// document.createElement("img");
																	// element.src
																	// =
																	// action.result.fileURL;
																	// if
																	// (Ext.isIE)
																	// {
																	// editor.insertAtCursor(element.outerHTML);
																	// } else {
																	// var
																	// selection
																	// =
																	// editor.win.getSelection();
																	// if
																	// (!selection.isCollapsed)
																	// {
																	// selection.deleteFromDocument();
																	// }
																	// selection.getRangeAt(0).insertNode(element);
																	// }
																	var url = action.result.result[0].fileURL;
																	var ele = "<img src='"
																			+ url
																			+ "' />";
																	editor
																			.insertAtCursor(ele);
																	win.hide();
																},
																failure : function(
																		form,
																		action) {
																	form
																			.reset();
																	if (action.failureType == Ext.form.Action.SERVER_INVALID)
																		Ext.MessageBox
																				.alert(
																						'警告',
																						action.result.errors[0].msg);
																}
															});
												}
											}, {
												text : '取消',
												type : 'submit',
												handler : function() {
													win.close(this);
												}
											} ]
								})

						var win = new Ext.Window({
							title : "上传图片",
							width : 350,
							height : 150,
							modal : true,
							border : false,
							iconCls : "picture.png",
							layout : "fit",
							items : imgform
						});
						win.show();
					},

					createToolbar : function(editor) {

						var tipsEnabled = Ext.QuickTips
								&& Ext.QuickTips.isEnabled();

						function btn(id, toggle, handler) {
							return {
								itemId : id,
								cls : 'x-btn-icon x-edit-' + id,
								enableToggle : toggle !== false,
								scope : editor,
								handler : handler || editor.relayBtnCmd,
								clickEvent : 'mousedown',
								tooltip : tipsEnabled ? editor.buttonTips[id]
										|| undefined : undefined,
								tabIndex : -1
							};
						}
						// build the toolbar
						var tb = new Ext.Toolbar({
							renderTo : this.wrap.dom.firstChild
						});
						// stop form submits
						tb.el.on('click', function(e) {
							e.preventDefault();
						});

						if (this.enableFont && !Ext.isSafari2) {
							this.fontSelect = tb.el.createChild({
								tag : 'select',
								cls : 'x-font-select',
								html : this.createFontOptions()
							});
							this.fontSelect.on('change', function() {
								var font = this.fontSelect.dom.value;
								this.relayCmd('fontname', font);
								this.deferFocus();
							}, this);
							tb.add(this.fontSelect.dom, '-');
						}
						;
						if (this.enableFormat) {
							tb
									.add(btn('bold'), btn('italic'),
											btn('underline'));
						}
						;
						if (this.enableFontSize) {
							tb.add('-', btn('increasefontsize', false,
									this.adjustFont), btn('decreasefontsize',
									false, this.adjustFont));
						}
						;
						if (this.enableColors) {
							tb
									.add(
											'-',
											{
												itemId : 'forecolor',
												cls : 'x-btn-icon x-edit-forecolor',
												clickEvent : 'mousedown',
												tooltip : tipsEnabled ? editor.buttonTips['forecolor']
														|| undefined
														: undefined,
												tabIndex : -1,
												menu : new Ext.menu.ColorMenu(
														{
															allowReselect : true,
															focus : Ext.emptyFn,
															value : '000000',
															plain : true,
															selectHandler : function(
																	cp, color) {
																this
																		.execCmd(
																				'forecolor',
																				Ext.isSafari
																						|| Ext.isIE ? '#'
																						+ color
																						: color);
																this
																		.deferFocus();
															},
															scope : this,
															clickEvent : 'mousedown'
														})
											},
											{
												itemId : 'backcolor',
												cls : 'x-btn-icon x-edit-backcolor',
												clickEvent : 'mousedown',
												tooltip : tipsEnabled ? editor.buttonTips['backcolor']
														|| undefined
														: undefined,
												tabIndex : -1,
												menu : new Ext.menu.ColorMenu(
														{
															focus : Ext.emptyFn,
															value : 'FFFFFF',
															plain : true,
															allowReselect : true,
															selectHandler : function(
																	cp, color) {
																if (Ext.isGecko) {
																	this
																			.execCmd(
																					'useCSS',
																					false);
																	this
																			.execCmd(
																					'hilitecolor',
																					color);
																	this
																			.execCmd(
																					'useCSS',
																					true);
																	this
																			.deferFocus();
																} else {
																	this
																			.execCmd(
																					Ext.isOpera ? 'hilitecolor'
																							: 'backcolor',
																					Ext.isSafari
																							|| Ext.isIE ? '#'
																							+ color
																							: color);
																	this
																			.deferFocus();
																}
															},
															scope : this,
															clickEvent : 'mousedown'
														})
											});
						}
						;
						if (this.enableAlignments) {
							tb.add('-', btn('justifyleft'),
									btn('justifycenter'), btn('justifyright'));
						}
						;
						if (!Ext.isSafari2) {
							if (this.enableLinks) {
								tb.add('-', btn('createlink', false,
										this.createLink));
							}
							;
							if (this.enableImages && this.uploadUrl != '') {
								tb.add('-', btn('createimage', false,
										this.createImage));
							}
							if (this.enableLists) {
								tb.add('-', btn('insertorderedlist'),
										btn('insertunorderedlist'));
							}
							if (this.enableSourceEdit) {
								tb.add('-', btn('sourceedit', true, function(
										btn) {
									this.toggleSourceEdit(btn.pressed);
								}));
							}
						}
						this.tb = tb;
					}
				});

function getServerTime() {
	if (typeof (__SERVER_TIME__) == 'function') {
		return __SERVER_TIME__();
	} else if (typeof (__SERVER_TIME__) == 'object') {
		return __SERVER_TIME__;
	} else {
		return new Date();
	}
}